+/**
+ * \brief Assuming the internal file pointer \ref gdcmDocument::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 gdcmDocument::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 gdcmDocument::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.
+ */
+guint32 gdcmDocument::ReadTagLength(guint16 TestGroup, guint16 TestElement)
+{
+ guint16 ItemTagGroup;
+ guint16 ItemTagElement;
+ long PositionOnEntry = ftell(fp);
+ long CurrentPosition = ftell(fp); // On debugging purposes
+
+ //// Read the Item Tag group and element, and make
+ // sure they are respectively 0xfffe and 0xe000:
+ ItemTagGroup = ReadInt16();
+ ItemTagElement = ReadInt16();
+ if ( (ItemTagGroup != TestGroup) || (ItemTagElement != TestElement ) )
+ {
+ std::ostringstream s;
+ s << " We should have found tag (";
+ s << std::hex << TestGroup << "," << TestElement << ")" << std::endl;
+ s << " but instead we encountered tag (";
+ s << std::hex << ItemTagGroup << "," << ItemTagElement << ")"
+ << std::endl;
+ s << " at address: " << (unsigned)CurrentPosition << std::endl;
+ dbg.Verbose(0, "gdcmDocument::ReadItemTagLength: wrong Item Tag found:");
+ dbg.Verbose(0, s.str().c_str());
+ fseek(fp, PositionOnEntry, SEEK_SET);
+ return 0;
+ }
+
+ //// Then read the associated Item Length
+ CurrentPosition=ftell(fp);
+ guint32 ItemLength;
+ ItemLength = ReadInt32();
+ {
+ std::ostringstream s;
+ s << "Basic Item Length is: "
+ << ItemLength << std::endl;
+ s << " at address: " << (unsigned)CurrentPosition << std::endl;
+ dbg.Verbose(0, "gdcmDocument::ReadItemTagLength: ", s.str().c_str());
+ }
+ return ItemLength;
+}
+
+/**
+ * \brief Read the length of an exptected Item tag i.e. (0xfffe, 0xe000).
+ * \sa \ref gdcmDocument::ReadTagLength
+ * \warning See warning of \ref gdcmDocument::ReadTagLength
+ * @return On success returns the length associated to the item tag.
+ * On failure returns 0.
+ */
+guint32 gdcmDocument::ReadItemTagLength(void)
+{
+ return ReadTagLength(0xfffe, 0xe000);
+}
+
+/**
+ * \brief Read the length of an exptected Sequence Delimiter tag i.e.
+ * (0xfffe, 0xe0dd).
+ * \sa \ref gdcmDocument::ReadTagLength
+ * \warning See warning of \ref gdcmDocument::ReadTagLength
+ * @return On success returns the length associated to the Sequence
+ * Delimiter tag. On failure returns 0.
+ */
+guint32 gdcmDocument::ReadSequenceDelimiterTagLength(void)
+{
+ return ReadTagLength(0xfffe, 0xe0dd);
+}
+
+
+/**
+ * \brief Parse pixel data from disk for multi-fragment Jpeg/Rle files
+ * No other way so 'skip' the Data
+ *
+ */
+void gdcmDocument::Parse7FE0 (void)
+{
+ gdcmDocEntry* Element = GetDocEntryByNumber(0x0002, 0x0010);
+ if ( !Element )
+ return;
+
+ if ( IsImplicitVRLittleEndianTransferSyntax()
+ || IsExplicitVRLittleEndianTransferSyntax()
+ || IsExplicitVRBigEndianTransferSyntax() /// \todo 1.2.2 ??? A verifier !
+ || IsDeflatedExplicitVRLittleEndianTransferSyntax() )
+ return;
+
+ // ---------------- for Parsing : Position on begining of Jpeg/RLE Pixels
+
+ //// Read the Basic Offset Table Item Tag length...
+ guint32 ItemLength = ReadItemTagLength();
+
+ //// ... and then read length[s] itself[themselves]. We don't use
+ // the values read (BTW what is the purpous of those lengths ?)
+ if (ItemLength != 0) {
+ // BTW, what is the purpous of those length anyhow !?
+ char * BasicOffsetTableItemValue = new char[ItemLength + 1];
+ fread(BasicOffsetTableItemValue, ItemLength, 1, fp);
+ for (unsigned int i=0; i < ItemLength; i += 4){
+ guint32 IndividualLength;
+ IndividualLength = str2num(&BasicOffsetTableItemValue[i],guint32);
+ std::ostringstream s;
+ s << " Read one length: ";
+ s << std::hex << IndividualLength << std::endl;
+ dbg.Verbose(0, "gdcmDocument::Parse7FE0: ", s.str().c_str());
+ }
+ }
+
+ if ( ! IsRLELossLessTransferSyntax() )
+ {
+ // JPEG Image
+
+ //// We then skip (not reading them) all the fragments of images:
+ while ( (ItemLength = ReadItemTagLength()) )
+ {
+ SkipBytes(ItemLength);
+ }
+
+ }
+ else
+ {
+ // RLE Image
+ long ftellRes;
+ long RleSegmentLength[15], fragmentLength;
+
+ // while 'Sequence Delimiter Item' (fffe,e0dd) not found
+ while ( (fragmentLength = ReadSequenceDelimiterTagLength()) )
+ {
+ // Parse fragments of the current Fragment (Frame)
+ //------------------ scanning (not reading) fragment pixels
+ guint32 nbRleSegments = ReadInt32();
+ printf(" Nb of RLE Segments : %d\n",nbRleSegments);
+
+ //// Reading RLE Segments Offset Table
+ guint32 RleSegmentOffsetTable[15];
+ for(int k=1; k<=15; k++) {
+ ftellRes=ftell(fp);
+ RleSegmentOffsetTable[k] = ReadInt32();
+ printf(" at : %x Offset Segment %d : %d (%x)\n",
+ (unsigned)ftellRes,k,RleSegmentOffsetTable[k],
+ RleSegmentOffsetTable[k]);
+ }
+
+ // skipping (not reading) RLE Segments
+ if (nbRleSegments>1) {
+ for(unsigned int k=1; k<=nbRleSegments-1; k++) {
+ RleSegmentLength[k]= RleSegmentOffsetTable[k+1]
+ - RleSegmentOffsetTable[k];
+ ftellRes=ftell(fp);
+ printf (" Segment %d : Length = %d x(%x) Start at %x\n",
+ k,(unsigned)RleSegmentLength[k],
+ (unsigned)RleSegmentLength[k], (unsigned)ftellRes);
+ SkipBytes(RleSegmentLength[k]);
+ }
+ }
+
+ RleSegmentLength[nbRleSegments]= fragmentLength
+ - RleSegmentOffsetTable[nbRleSegments];
+ ftellRes=ftell(fp);
+ printf (" Segment %d : Length = %d x(%x) Start at %x\n",
+ nbRleSegments,(unsigned)RleSegmentLength[nbRleSegments],
+ (unsigned)RleSegmentLength[nbRleSegments],(unsigned)ftellRes);
+ SkipBytes(RleSegmentLength[nbRleSegments]);
+ }
+ }
+}
+
+/**
+ * \brief Compares two documents, according to \ref gdcmDicomDir rules
+ * \warning Does NOT work with ACR-NEMA files
+ * \todo Find a trick to solve the pb (use RET fields ?)
+ * @param document
+ * @return true if 'smaller'
+ */
+bool gdcmDocument::operator<(gdcmDocument &document)
+{
+ std::string s1,s2;
+
+ // Patient Name
+ s1=this->GetEntryByNumber(0x0010,0x0010);
+ s2=document.GetEntryByNumber(0x0010,0x0010);
+ if(s1 < s2)
+ return true;
+ else if(s1 > s2)
+ return false;
+ else
+ {
+ // Patient ID
+ s1=this->GetEntryByNumber(0x0010,0x0020);
+ s2=document.GetEntryByNumber(0x0010,0x0020);
+ if (s1 < s2)
+ return true;
+ else if (s1 > s2)
+ return true;
+ else
+ {
+ // Study Instance UID
+ s1=this->GetEntryByNumber(0x0020,0x000d);
+ s2=document.GetEntryByNumber(0x0020,0x000d);
+ if (s1 < s2)
+ return true;
+ else if(s1 > s2)
+ return false;
+ else
+ {
+ // Serie Instance UID
+ s1=this->GetEntryByNumber(0x0020,0x000e);
+ s2=document.GetEntryByNumber(0x0020,0x000e);
+ if (s1 < s2)
+ return true;
+ else if(s1 > s2)
+ return false;
+ }
+ }
+ }
+
+ return false;
+}