- elem = SwapShort(elem);
- }
- }
-}
-
-/**
- * \brief Read the next tag but WITHOUT loading it's value
- * (read the 'Group Number', the 'Element Number',
- * gets the Dict Entry
- * gets the VR, gets the length, gets the offset value)
- * @return On succes the newly created DocEntry, NULL on failure.
- */
-DocEntry *Document::ReadNextDocEntry()
-{
- uint16_t group;
- uint16_t elem;
-
- try
- {
- group = ReadInt16();
- elem = ReadInt16();
- }
- catch ( FormatError e )
- {
- // We reached the EOF (or an error occured) therefore
- // header parsing has to be considered as finished.
- //std::cout << e;
- return 0;
- }
-
- // Sometimes file contains groups of tags with reversed endianess.
- HandleBrokenEndian(group, elem);
-
-// In 'true DICOM' files Group 0002 is always little endian
- if ( HasDCMPreamble )
- HandleOutOfGroup0002(group, elem);
-
- std::string vr = FindDocEntryVR();
- std::string realVR = vr;
-
- if( vr == GDCM_UNKNOWN)
- {
- DictEntry *dictEntry = GetDictEntry(group,elem);
- if( dictEntry )
- realVR = dictEntry->GetVR();
- }
-
- DocEntry *newEntry;
- if( Global::GetVR()->IsVROfSequence(realVR) )
- newEntry = NewSeqEntry(group, elem);
- else if( Global::GetVR()->IsVROfStringRepresentable(realVR) )
- newEntry = NewValEntry(group, elem,vr);
- else
- newEntry = NewBinEntry(group, elem,vr);
-
- if( vr == GDCM_UNKNOWN )
- {
- if( Filetype == ExplicitVR )
- {
- // We thought this was explicit VR, but we end up with an
- // implicit VR tag. Let's backtrack.
- std::string msg;
- msg = Util::Format("Falsely explicit vr file (%04x,%04x)\n",
- newEntry->GetGroup(), newEntry->GetElement());
- gdcmVerboseMacro( msg.c_str() );
- }
- newEntry->SetImplicitVR();
- }
-
- try
- {
- FindDocEntryLength(newEntry);
- }
- catch ( FormatError e )
- {
- // Call it quits
- //std::cout << e;
- delete newEntry;
- return 0;
- }
-
- newEntry->SetOffset(Fp->tellg());
-
- return newEntry;
-}
-
-
-/**
- * \brief Generate a free TagKey i.e. a TagKey that is not present
- * in the TagHt dictionary.
- * @param group The generated tag must belong to this group.
- * @return The element of tag with given group which is fee.
- */
-uint32_t Document::GenerateFreeTagKeyInGroup(uint16_t group)
-{
- for (uint32_t elem = 0; elem < UINT32_MAX; elem++)
- {
- TagKey key = DictEntry::TranslateToKey(group, elem);
- if (TagHT.count(key) == 0)
- {
- return elem;
- }
- }
- return UINT32_MAX;
-}
-
-/**
- * \brief Assuming the internal file pointer \ref Document::Fp
- * is placed at the beginning of a tag check whether this
- * tag is (TestGroup, TestElement).
- * \warning On success the internal file pointer \ref Document::Fp
- * is modified to point after the tag.
- * On failure (i.e. when the tag wasn't the expected tag
- * (TestGroup, TestElement) the internal file pointer
- * \ref Document::Fp is restored to it's original position.
- * @param testGroup The expected group of the tag.
- * @param testElement The expected Element of the tag.
- * @return True on success, false otherwise.
- */
-bool Document::ReadTag(uint16_t testGroup, uint16_t testElement)
-{
- long positionOnEntry = Fp->tellg();
- long currentPosition = Fp->tellg(); // On debugging purposes
-
- //// Read the Item Tag group and element, and make
- // sure they are what we expected:
- uint16_t itemTagGroup;
- uint16_t itemTagElement;
- try
- {
- itemTagGroup = ReadInt16();
- itemTagElement = ReadInt16();
- }
- catch ( FormatError e )
- {
- //std::cerr << e << std::endl;
- return false;
- }
- if ( itemTagGroup != testGroup || itemTagElement != testElement )
- {
- gdcmVerboseMacro( "Wrong Item Tag found:"
- << " We should have found tag ("
- << std::hex << testGroup << "," << testElement << ")" << std::endl
- << " but instead we encountered tag ("
- << std::hex << itemTagGroup << "," << itemTagElement << ")"
- << " at address: " << " 0x(" << (unsigned int)currentPosition << ")"
- ) ;
- Fp->seekg(positionOnEntry, std::ios::beg);
-
- return false;
- }
- return true;
-}
-
-/**
- * \brief Assuming the internal file pointer \ref Document::Fp
- * is placed at the beginning of a tag (TestGroup, TestElement),
- * read the length associated to the Tag.
- * \warning On success the internal file pointer \ref Document::Fp
- * is modified to point after the tag and it's length.
- * On failure (i.e. when the tag wasn't the expected tag
- * (TestGroup, TestElement) the internal file pointer
- * \ref Document::Fp is restored to it's original position.
- * @param testGroup The expected group of the tag.
- * @param testElement The expected Element of the tag.
- * @return On success returns the length associated to the tag. On failure
- * returns 0.
- */
-uint32_t Document::ReadTagLength(uint16_t testGroup, uint16_t testElement)
-{
- long positionOnEntry = Fp->tellg();
- (void)positionOnEntry;
-
- if ( !ReadTag(testGroup, testElement) )
- {
- return 0;
- }
-
- //// Then read the associated Item Length
- long currentPosition = Fp->tellg();
- uint32_t itemLength = ReadInt32();
- {
- gdcmVerboseMacro( "Basic Item Length is: "
- << itemLength << std::endl
- << " at address: " << std::hex << (unsigned int)currentPosition);
- }
- return itemLength;
-}
-
-/**
- * \brief When parsing the Pixel Data of an encapsulated file, read
- * the basic offset table (when present, and BTW dump it).
- */
-void Document::ReadAndSkipEncapsulatedBasicOffsetTable()
-{
- //// Read the Basic Offset Table Item Tag length...
- uint32_t itemLength = ReadTagLength(0xfffe, 0xe000);
-
- // When present, read the basic offset table itself.
- // Notes: - since the presence of this basic offset table is optional
- // we can't rely on it for the implementation, and we will simply
- // trash it's content (when present).
- // - still, when present, we could add some further checks on the
- // lengths, but we won't bother with such fuses for the time being.
- if ( itemLength != 0 )
- {
- char *basicOffsetTableItemValue = new char[itemLength + 1];
- Fp->read(basicOffsetTableItemValue, itemLength);
-
-#ifdef GDCM_DEBUG
- for (unsigned int i=0; i < itemLength; i += 4 )
- {
- uint32_t individualLength = str2num( &basicOffsetTableItemValue[i],
- uint32_t);
- gdcmVerboseMacro( "Read one length: " <<
- std::hex << individualLength );
- }
-#endif //GDCM_DEBUG
-
- delete[] basicOffsetTableItemValue;
- }
-}
-
-/**
- * \brief Parse pixel data from disk of [multi-]fragment RLE encoding.
- * Compute the RLE extra information and store it in \ref RLEInfo
- * for later pixel retrieval usage.
- */
-void Document::ComputeRLEInfo()
-{
- std::string ts = GetTransferSyntax();
- if ( !Global::GetTS()->IsRLELossless(ts) )
- {
- return;
- }
-
- // Encoded pixel data: for the time being we are only concerned with
- // Jpeg or RLE Pixel data encodings.
- // As stated in PS 3.5-2003, section 8.2 p44:
- // "If sent in Encapsulated Format (i.e. other than the Native Format) the
- // value representation OB is used".
- // Hence we expect an OB value representation. Concerning OB VR,
- // the section PS 3.5-2003, section A.4.c p 58-59, states:
- // "For the Value Representations OB and OW, the encoding shall meet the
- // following specifications depending on the Data element tag:"
- // [...snip...]
- // - the first item in the sequence of items before the encoded pixel
- // data stream shall be basic offset table item. The basic offset table
- // item value, however, is not required to be present"
-
- ReadAndSkipEncapsulatedBasicOffsetTable();
-
- // Encapsulated RLE Compressed Images (see PS 3.5-2003, Annex G)
- // Loop on the individual frame[s] and store the information
- // on the RLE fragments in a RLEFramesInfo.
- // Note: - when only a single frame is present, this is a
- // classical image.
- // - when more than one frame are present, then we are in
- // the case of a multi-frame image.
- long frameLength;
- while ( (frameLength = ReadTagLength(0xfffe, 0xe000)) )
- {
- // Parse the RLE Header and store the corresponding RLE Segment
- // Offset Table information on fragments of this current Frame.
- // Note that the fragment pixels themselves are not loaded
- // (but just skipped).
- long frameOffset = Fp->tellg();
-
- uint32_t nbRleSegments = ReadInt32();
- if ( nbRleSegments > 16 )
- {
- // There should be at most 15 segments (refer to RLEFrame class)
- gdcmVerboseMacro( "Too many segments.");
- }
-
- uint32_t rleSegmentOffsetTable[16];
- for( int k = 1; k <= 15; k++ )
- {
- rleSegmentOffsetTable[k] = ReadInt32();