+#endif //GDCM_WORDS_BIGENDIAN
+
+
+ fp->close();
+ delete fp;
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Protected
+/**
+ * \brief Initialize a default DICOM File that should contain all the
+ * field require by other reader. DICOM standard does not
+ * explicitely defines those fields, heuristic has been choosen.
+ * This is not perfect as we are writting a CT image...
+ */
+void File::InitializeDefaultFile()
+{
+ std::string date = Util::GetCurrentDate();
+ std::string time = Util::GetCurrentTime();
+ std::string uid = Util::CreateUniqueUID();
+ std::string uidMedia = uid;
+ std::string uidInst = uid;
+ std::string uidClass = Util::CreateUniqueUID();
+ std::string uidStudy = Util::CreateUniqueUID();
+ std::string uidSerie = Util::CreateUniqueUID();
+
+ // Meta Element Group Length
+ InsertValEntry("146 ", 0x0002, 0x0000);
+ // Media Storage SOP Class UID (CT Image Storage)
+ InsertValEntry("1.2.840.10008.5.1.4.1.1.2", 0x0002, 0x0002);
+ // Media Storage SOP Instance UID
+ InsertValEntry(uidClass.c_str(), 0x0002, 0x0003);
+ // Transfer Syntax UID (Explicit VR Little Endian)
+ InsertValEntry("1.2.840.10008.1.2.1 ", 0x0002, 0x0010);
+ // META Implementation Class UID
+ InsertValEntry(uidClass.c_str(), 0x0002, 0x0012);
+ // Source Application Entity Title
+ InsertValEntry("GDCM", 0x0002, 0x0016);
+
+ // Instance Creation Date
+ InsertValEntry(date.c_str(), 0x0008, 0x0012);
+ // Instance Creation Time
+ InsertValEntry(time.c_str(), 0x0008, 0x0013);
+ // SOP Class UID
+ InsertValEntry("1.2.840.10008.5.1.4.1.1.2", 0x0008, 0x0016);
+ // SOP Instance UID
+ InsertValEntry(uidInst.c_str(), 0x0008, 0x0018);
+ // Modality
+ InsertValEntry("CT", 0x0008, 0x0060);
+ // Manufacturer
+ InsertValEntry("GDCM", 0x0008, 0x0070);
+ // Institution Name
+ InsertValEntry("GDCM", 0x0008, 0x0080);
+ // Institution Address
+ InsertValEntry("http://www-creatis.insa-lyon.fr/Public/Gdcm", 0x0008, 0x0081);
+
+ // Patient's Name
+ InsertValEntry("GDCM", 0x0010, 0x0010);
+ // Patient ID
+ InsertValEntry("GDCMID", 0x0010, 0x0020);
+
+ // Study Instance UID
+ InsertValEntry(uidStudy.c_str(), 0x0020, 0x000d);
+ // Series Instance UID
+ InsertValEntry(uidSerie.c_str(), 0x0020, 0x000e);
+ // StudyID
+ InsertValEntry("1", 0x0020, 0x0010);
+ // SeriesNumber
+ InsertValEntry("1", 0x0020, 0x0011);
+
+ // Samples per pixel 1 or 3
+ InsertValEntry("1", 0x0028, 0x0002);
+ // photochromatic interpretation
+ InsertValEntry("MONOCHROME1", 0x0028, 0x0004);
+ // nbRows
+ InsertValEntry("0", 0x0028, 0x0010);
+ // nbCols
+ InsertValEntry("0", 0x0028, 0x0011);
+ // BitsAllocated 8 or 12 or 16
+ InsertValEntry("8", 0x0028, 0x0100);
+ // BitsStored <= BitsAllocated
+ InsertValEntry("8", 0x0028, 0x0101);
+ // HighBit <= BitsAllocated - 1
+ InsertValEntry("7", 0x0028, 0x0102);
+ // Pixel Representation 0(unsigned) or 1(signed)
+ InsertValEntry("0", 0x0028, 0x0103);
+
+ // default value
+ // Special case this is the image (not a string)
+ GrPixel = 0x7fe0;
+ NumPixel = 0x0010;
+ InsertBinEntry(0, 0, GrPixel, NumPixel);
+}
+
+//-----------------------------------------------------------------------------
+// Private
+/**
+ * \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 File::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)
+ gdcmWarningMacro( "Too many segments.");
+ }
+
+ uint32_t rleSegmentOffsetTable[16];
+ for( int k = 1; k <= 15; k++ )
+ {
+ rleSegmentOffsetTable[k] = ReadInt32();
+ }
+
+ // Deduce from both the RLE Header and the 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 at the end of the item we encounter a 'Sequence
+ // Delimiter Item':
+ if ( !ReadTag(0xfffe, 0xe0dd) )
+ {
+ 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;
+ }
+
+ ReadAndSkipEncapsulatedBasicOffsetTable();
+
+ // Loop on the fragments[s] and store the parsed information in a
+ // JPEGInfo.
+ long fragmentLength;
+ while ( (fragmentLength = ReadTagLength(0xfffe, 0xe000)) )
+ {
+ long fragmentOffset = Fp->tellg();
+
+ // Store the collected info
+ JPEGFragment *newFragment = new JPEGFragment;
+ newFragment->SetOffset(fragmentOffset);
+ newFragment->SetLength(fragmentLength);
+ JPEGInfo->AddFragment(newFragment);
+
+ SkipBytes(fragmentLength);
+ }