+
+ // Deduce from both RLE Header and frameLength
+ // the fragment length, and again store this info
+ // in a RLEFramesInfo.
+ long rleSegmentLength[15];
+ // skipping (not reading) RLE Segments
+ if ( nbRleSegments > 1)
+ {
+ for(unsigned int k = 1; k <= nbRleSegments-1; k++)
+ {
+ rleSegmentLength[k] = rleSegmentOffsetTable[k+1]
+ - rleSegmentOffsetTable[k];
+ SkipBytes(rleSegmentLength[k]);
+ }
+ }
+
+ rleSegmentLength[nbRleSegments] = frameLength
+ - rleSegmentOffsetTable[nbRleSegments];
+ SkipBytes(rleSegmentLength[nbRleSegments]);
+
+ // Store the collected info
+ RLEFrame *newFrame = new RLEFrame;
+ newFrame->SetNumberOfFragments(nbRleSegments);
+ for( unsigned int uk = 1; uk <= nbRleSegments; uk++ )
+ {
+ newFrame->SetOffset(uk,frameOffset + rleSegmentOffsetTable[uk]);
+ newFrame->SetLength(uk,rleSegmentLength[uk]);
+ }
+ RLEInfo->AddFrame(newFrame);
+ }
+
+ // Make sure that we encounter a 'Sequence Delimiter Item'
+ // at the end of the item :
+ if ( !ReadTag(0xfffe, 0xe0dd) ) // once per RLE File
+ {
+ gdcmWarningMacro( "No sequence delimiter item at end of RLE item sequence");
+ }
+}
+
+/**
+ * \brief Parse pixel data from disk of [multi-]fragment Jpeg encoding.
+ * Compute the jpeg extra information (fragment[s] offset[s] and
+ * length) and store it[them] in \ref JPEGInfo for later pixel
+ * retrieval usage.
+ */
+void File::ComputeJPEGFragmentInfo()
+{
+ // If you need to, look for comments of ComputeRLEInfo().
+ std::string ts = GetTransferSyntax();
+ if ( ! Global::GetTS()->IsJPEG(ts) )
+ {
+ return;
+ }
+
+ ReadEncapsulatedBasicOffsetTable();
+
+ // Loop on the fragments[s] and store the parsed information in a
+ // JPEGInfo.
+ long fragmentLength;
+ int i=0;
+ uint32_t sum = 0;
+ while ( (fragmentLength = ReadTagLength(0xfffe, 0xe000)) != 0 )
+ {
+ // Since we have read the basic offset table, let's check the value were correct
+ // or else produce a warning:
+ // A.4 Transfer syntaxes for encapsulation of encoded pixel data:
+ // When the Item Value is present, the Basic Offset Table Item Value shall contain
+ // concatenated 32-bit unsigned integer values that are byte offsets to the first
+ // byte of the Item Tag of the first fragment for each frame in the Sequence of
+ // Items. These offsets are measured from the first byte of the first Item Tag
+ // following the Basic Offset Table item (See Table A.4-2).
+
+ if ( BasicOffsetTableItemValue )
+ {
+ // If a BasicOffsetTableItemValue was read
+ uint32_t individualLength = BasicOffsetTableItemValue[i];
+ //assert( individualLength == sum ); // Seems like 00191113.dcm is off by one ??
+ if( individualLength != sum )
+ {
+ gdcmWarningMacro( "BasicOffsetTableItemValue differs from the fragment lenght:" <<
+ individualLength << " != " << sum );
+ }
+ sum += fragmentLength + 8;
+ i++;
+ }
+
+ long fragmentOffset = Fp->tellg(); // Once per fragment
+ // Store the collected info
+ JPEGFragment *newFragment = new JPEGFragment;
+ newFragment->SetOffset(fragmentOffset);
+ newFragment->SetLength(fragmentLength);
+ JPEGInfo->AddFragment(newFragment);
+
+ SkipBytes(fragmentLength);
+ }
+
+ // Make sure that we encounter a 'Sequence Delimiter Item'
+ // at the end of the item :
+ if ( !ReadTag(0xfffe, 0xe0dd) )
+ {
+ gdcmWarningMacro( "No sequence delimiter item at end of JPEG item sequence");
+ }
+}
+
+/**
+ * \brief Assuming the internal file pointer \ref Document::Fp
+ * is placed at the beginning of a tag, check whether this
+ * tag is (TestGroup, TestElem).
+ * \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, TestElem) the internal file pointer
+ * \ref Document::Fp is restored to it's original position.
+ * @param testGroup The expected group of the tag.
+ * @param testElem The expected Element of the tag.
+ * @return True on success, false otherwise.
+ */
+bool File::ReadTag(uint16_t testGroup, uint16_t testElem)
+{
+ long positionOnEntry = Fp->tellg(); // Only when reading fragments
+ //long currentPosition = positionOnEntry; // On debugging purposes
+
+ // Read the Item Tag group and element, and make
+ // sure they are what we expected:
+ uint16_t itemTagGroup;
+ uint16_t itemTagElem;
+ try
+ {
+ itemTagGroup = ReadInt16();
+ itemTagElem = ReadInt16();
+ }
+ catch ( FormatError )
+ {
+ gdcmErrorMacro( "Can not read tag for "
+ << " We should have found tag ("
+ << DictEntry::TranslateToKey(testGroup,testElem) << ")"
+ ) ;
+
+ return false;
+ }
+ if ( itemTagGroup != testGroup || itemTagElem != testElem )
+ {
+ // in order not to pollute output we don't warn on 'delimitors'
+ if (itemTagGroup != 0xfffe || testGroup != 0xfffe )
+ gdcmWarningMacro( "Wrong Item Tag found:"
+ << " We should have found tag ("
+ << DictEntry::TranslateToKey(testGroup,testElem) << ")" << std::endl
+ << " but instead we encountered tag ("
+ << DictEntry::TranslateToKey(itemTagGroup,itemTagElem) << ")"
+ << " at address: " << " 0x(" << std::hex
+ << (unsigned int)positionOnEntry << std::dec << ")"
+ ) ;
+ Fp->seekg(positionOnEntry, std::ios::beg);
+
+ return false;