]> Creatis software - gdcm.git/commitdiff
* FIX taking into account the possible 7fe0,0010 multiplicity
authorjpr <jpr>
Mon, 2 Feb 2004 18:36:16 +0000 (18:36 +0000)
committerjpr <jpr>
Mon, 2 Feb 2004 18:36:16 +0000 (18:36 +0000)
     * FIX add GRPixel,NumPixel,countGrPixel (gdcmParser protected members)
           to allow removal of references to 7fe0,0010, to deal with
   ACR-NEMA images, when 0028,0200 is meaningfull

src/gdcmFile.cxx
src/gdcmFile.h
src/gdcmHeader.cxx
src/gdcmHeader.h
src/gdcmHeaderHelper.cxx
src/gdcmParser.cxx
src/gdcmParser.h

index e8de0b97dcc03bfbc24a2ca7fd6c72bb669f17aa..2bb43980229a7a88af084b7f2ab16ac5d0884d41 100644 (file)
@@ -684,11 +684,12 @@ bool gdcmFile::WriteBase (std::string fileName, FileType type) {
    // ----------------- End of Special Patch ----------------
    
    // TODO : get the grPixel, numPixel values (for some ACR-NEMA images only)
-   guint16 grPixel =0x7fe0;
-   guint16 numPixel=0x0010;
+   
+   guint16 grPixel =Header->GetGrPixel();
+   guint16 numPixel=Header->GetNumPixel();;
     
    // Update Pixel Data Length
-   // the *last* of the 7fe0,0010, if many.
+   // the *last* of the (GrPixel, NumPixel), if many.
           
    TagKey key = gdcmDictEntry::TranslateToKey(grPixel, numPixel); 
    TagHeaderEntryHT::iterator p2;
index d03f98e01e4377691b874266f6fbdcbf212aa04e..11c046db913f98dea214b0a1ec3b95e9b9cf790f 100644 (file)
@@ -101,7 +101,7 @@ private:
                       // ==-1 if ImageData never read.
 
    int Parsed;               // weather already parsed
-   std::string OrigFileName; // To avoid file overwrite
+   std::string OrigFileName; // To avoid file overwrite   
 };
 
 //-----------------------------------------------------------------------------
index fdfc651c33d222fa063a699145714855c5d8be3e..60eb0fc065f7ccf78379973285f64a33e957979c 100644 (file)
@@ -31,7 +31,36 @@ gdcmHeader::gdcmHeader(const char *InFilename,
                        bool enable_sequences, 
                       bool ignore_shadow):
    gdcmParser(InFilename,exception_on_error,enable_sequences,ignore_shadow)
-{
+{ 
+   
+   // for some ACR-NEMA images GrPixel, NumPixel is *not* 7fe0,0010
+   // We may encounter the 'RETired' (0x0028, 0x0200) tag
+   // (Image Location") . This Element contains the number of
+   // the group that contains the pixel data (hence the "Pixel Data"
+   // is found by indirection through the "Image Location").
+   // Inside the group pointed by "Image Location" the searched element
+   // is conventionally the element 0x0010 (when the norm is respected).
+   // When the "Image Location" is absent we default to group 0x7fe0.
+   
+   // This IS the right place for the code
+      std::string ImageLocation = GetEntryByNumber(0x0028, 0x0200);
+      if ( ImageLocation == GDCM_UNFOUND ) { // Image Location
+         GrPixel = 0x7fe0;                   // default value
+      } else {
+         GrPixel = (guint16) atoi( ImageLocation.c_str() );
+      }   
+      if (GrPixel == 0xe07f) // sometimes Image Location value doesn't follow 
+         GrPixel = 0x7fe0;   // the supposed processor endianity. 
+                             // see gdcmData/cr172241.dcm      
+      if (GrPixel != 0x7fe0) 
+         // This is a kludge for old dirty Philips imager.
+         NumPixel = 0x1010;
+      else
+         NumPixel = 0x0010;
+        
+      TagKey key = gdcmDictEntry::TranslateToKey(GrPixel, NumPixel);
+      countGrPixel = GetEntry().count(key);       
 }
 
 /**
@@ -298,7 +327,7 @@ int gdcmHeader::GetZSize(void) {
  * @return  The encountered number of Bits Stored, 0 by default.
  *          0 means the file is NOT USABLE. The caller has to check it !
  */
-int gdcmHeader::GetBitsStored(void) { 
+int gdcmHeader::GetBitsStored(void) {  
    std::string StrSize = GetEntryByNumber(0x0028,0x0101);
    if (StrSize == GDCM_UNFOUND)
       return 0;  // It's supposed to be mandatory
@@ -314,7 +343,7 @@ int gdcmHeader::GetBitsStored(void) {
  * @return  The encountered number of Bits Allocated, 0 by default.
  *          0 means the file is NOT USABLE. The caller has to check it !
  */
-int gdcmHeader::GetBitsAllocated(void) { 
+int gdcmHeader::GetBitsAllocated(void) {  // TODO : move to gdcmFile
    std::string StrSize = GetEntryByNumber(0x0028,0x0100);
    if (StrSize == GDCM_UNFOUND)
       return 0; // It's supposed to be mandatory
@@ -330,7 +359,7 @@ int gdcmHeader::GetBitsAllocated(void) {
  * @return  The encountered number of Samples Per Pixel, 1 by default.
  *          (Gray level Pixels)
  */
-int gdcmHeader::GetSamplesPerPixel(void) { 
+int gdcmHeader::GetSamplesPerPixel(void) {  // TODO : move to gdcmFile
    std::string StrSize = GetEntryByNumber(0x0028,0x0002);
    if (StrSize == GDCM_UNFOUND)
       return 1; // Well, it's supposed to be mandatory ...
@@ -345,7 +374,7 @@ int gdcmHeader::GetSamplesPerPixel(void) {
  * 
  * @return  The encountered Planar Configuration, 0 by default.
  */
-int gdcmHeader::GetPlanarConfiguration(void) { 
+int gdcmHeader::GetPlanarConfiguration(void) {
    std::string StrSize = GetEntryByNumber(0x0028,0x0006);
    if (StrSize == GDCM_UNFOUND)
       return 0;
@@ -384,7 +413,7 @@ int gdcmHeader::GetPixelSize(void) {
  * \        24 bit images appear as 8 bit
  * @return  0S if nothing found. NOT USABLE file. The caller has to check
  */
-std::string gdcmHeader::GetPixelType(void) {
+std::string gdcmHeader::GetPixelType(void) { 
    std::string BitsAlloc = GetEntryByNumber(0x0028, 0x0100); // Bits Allocated
    if (BitsAlloc == GDCM_UNFOUND) {
       dbg.Verbose(0, "gdcmHeader::GetPixelType: unfound Bits Allocated");
@@ -408,27 +437,25 @@ std::string gdcmHeader::GetPixelType(void) {
    return( BitsAlloc + Signed);
 }
 
+
 /**
  * \ingroup gdcmHeader
  * \brief   Recover the offset (from the beginning of the file) 
  * \        of *image* pixels (not *icone image* pixels, if any !)
  */
-size_t gdcmHeader::GetPixelOffset(void) {
-   // We may encounter the 'RETired' (0x0028, 0x0200) tag
-   // (Image Location") . This Element contains the number of
-   // the group that contains the pixel data (hence the "Pixel Data"
-   // is found by indirection through the "Image Location").
-   // Inside the group pointed by "Image Location" the searched element
-   // is conventionally the element 0x0010 (when the norm is respected).
-   // When the "Image Location" is absent we default to group 0x7fe0.
+size_t gdcmHeader::GetPixelOffset(void) { // TODO : move to gdcmFile
+
    //
    // If the element (0x0088,0x0200) 'icone image sequence' is found
    // (grPixel,numPixel) is stored twice : the first one for the icon
    // the second one for the image ...
    // pb : sometimes , (0x0088,0x0200) exists, but doesn't contain *anything*
    // see gdcmData/MxTwinLossLess.dcm ...
-   guint16 grPixel;
-   guint16 numPixel;
+   
+   
+   /*
+   guint16 grPixel = GrPixel;
+   guint16 numPixel= NumPixel;
    std::string ImageLocation = GetEntryByNumber(0x0028, 0x0200);
 
    if ( ImageLocation == GDCM_UNFOUND ) { // Image Location
@@ -446,13 +473,15 @@ size_t gdcmHeader::GetPixelOffset(void) {
       numPixel = 0x1010;
    else
       numPixel = 0x0010;
+ */
       
-   IterHT it = GetHeaderEntrySameNumber(grPixel,numPixel);          
+   IterHT it = GetHeaderEntrySameNumber(GrPixel,NumPixel);          
    //std::string icone = GetEntryByNumber(0x0088,0x0200); //icone image sequence
-   TagKey key = gdcmDictEntry::TranslateToKey(grPixel,numPixel);
+   TagKey key = gdcmDictEntry::TranslateToKey(GrPixel,NumPixel);
    gdcmHeaderEntry* PixelElement;
   
-   if (tagHT.count(key) == 1)   
+   //if (tagHT.count(key) == 1)
+   if (countGrPixel == 1)   
       PixelElement = (it.first)->second;
    else
       PixelElement = (++it.first)->second;
@@ -470,6 +499,8 @@ size_t gdcmHeader::GetPixelOffset(void) {
  *  @return 0 by default. NOT USABLE file. The caller has to check.
  */
 size_t gdcmHeader::GetPixelAreaLength(void) {
+
+/*
    // If this file complies with the norm we should encounter the
    // "Image Location" tag (0x0028,  0x0200). This tag contains the
    // the group that contains the pixel data (hence the "Pixel Data"
@@ -477,8 +508,10 @@ size_t gdcmHeader::GetPixelAreaLength(void) {
    // Inside the group pointed by "Image Location" the searched element
    // is conventionally the element 0x0010 (when the norm is respected).
    // When the "Image Location" is absent we default to group 0x7fe0.
+   
+
    guint16 grPixel;
-   guint16 numPixel;
+   guint16 numPixel;   
    std::string ImageLocation = GetEntryByNumber(0x0028, 0x0200);
    if ( ImageLocation == GDCM_UNFOUND ) { // Image Location
       grPixel = 0x7fe0;                   // default value
@@ -493,13 +526,15 @@ size_t gdcmHeader::GetPixelAreaLength(void) {
       numPixel = 0x1010;
    else
       numPixel = 0x0010;
+ */
               
-   IterHT it = GetHeaderEntrySameNumber(grPixel,numPixel);          
+   IterHT it = GetHeaderEntrySameNumber(GrPixel,NumPixel);          
    //std::string icone = GetEntryByNumber(0x0088,0x0200); //icone image sequence
-   TagKey key = gdcmDictEntry::TranslateToKey(grPixel,numPixel);
+   TagKey key = gdcmDictEntry::TranslateToKey(GrPixel,NumPixel);
    gdcmHeaderEntry* PixelElement;
   
-   if (tagHT.count(key) == 1)   
+  // if (tagHT.count(key) == 1) 
+  if (countGrPixel)  
       PixelElement = (it.first)->second;
    else
       PixelElement = (++it.first)->second;
@@ -508,7 +543,7 @@ size_t gdcmHeader::GetPixelAreaLength(void) {
       return PixelElement->GetLength();
    else {
       std::cout << "Big trouble : Pixel Element ("
-                << std::hex << grPixel<<","<< numPixel<< ") NOT found" 
+                << std::hex << GrPixel<<","<< NumPixel<< ") NOT found" 
                 << std::endl;
       return 0;
    }
@@ -742,19 +777,19 @@ std::string gdcmHeader::GetTransfertSyntaxName(void) {
  */
 void gdcmHeader::SetImageDataSize(size_t ImageDataSize) {
    std::string content1;
-   char car[20];       
-   // Assumes HeaderEntry (0x7fe0, 0x0010) exists ...
-   // TODO define private members PixelGroupNumber, PicxelElementNumber
-   //      update them, use them (only necessary for ACR-NEMA, not DICOM)      
+   char car[20];
+       
+   // Assumes HeaderEntry (GrPixel, NumPixel) is unique ...   
+   // TODO deal with multiplicity (see gdcmData/icone.dcm)     
    sprintf(car,"%d",ImageDataSize);
  
-   gdcmHeaderEntry *a = GetHeaderEntryByNumber(0x7fe0, 0x0010);
+   gdcmHeaderEntry *a = GetHeaderEntryByNumber(GrPixel, NumPixel);
    a->SetLength(ImageDataSize);
                
    ImageDataSize+=8;
    sprintf(car,"%d",ImageDataSize);
    content1=car;       
-   SetEntryByNumber(content1, 0x7fe0, 0x0000);
+   SetEntryByNumber(content1, GrPixel, NumPixel);
 }
 
 //-----------------------------------------------------------------------------
index 1e1e52091e0042f80161d2ee16fd355df793c24e..7c486e83ff73f4f51cde6eddf92467db5742a200 100644 (file)
@@ -111,6 +111,7 @@ protected:
    int anonymize(std::ostream&);  // FIXME : anonymize should be a friend ?
 
 private:
+
 };
 
 //-----------------------------------------------------------------------------
index 95128a194ba324ff094eb617e0f99cab032f41ed..27aafc3de3e535e5950b2220673feed9b7fff60f 100644 (file)
@@ -37,6 +37,8 @@
    int GetDir(std::string dPath, std::list<std::string> &filenames)
    {
     DIR *dir = opendir( dPath.c_str() );
+    if (dir == NULL)
+       return false;
     struct dirent *entry;
     while((entry = readdir(dir)) != NULL)
     {
@@ -123,7 +125,7 @@ int gdcmHeaderHelper::GetPixelSize() {
  *          - FD    Double,
  * \warning 12 bit images appear as 16 bit.
  * \        24 bit images appear as 8 bit
- * \        DOUBLE images are coded as 64 bit
+ * \        64 bit means 'DOUBLE' image
  * \               (no DOUBLE images in kosher DICOM,
  * \                but so usefull for people that miss them ;-)
  * @return  
index a155c2936265f7acd1cd7aaa1d2ff91f753e096d..f20135a53bb57f7acfee3dbaa149bc971dc8477a 100644 (file)
@@ -104,8 +104,9 @@ gdcmParser::gdcmParser(const char *InFilename,
 
    if ( !OpenFile(exception_on_error))
       return;
-   if (ParseHeader())
+   if (ParseHeader()) {
      LoadHeaderEntries();
+   }
    CloseFile();
 
    wasUpdated = 0;  // will be set to 1 if user adds an entry
@@ -381,7 +382,7 @@ bool gdcmParser::CloseFile(void) {
  */
 bool gdcmParser::Write(FILE *fp, FileType type) {
 // ==============
-// TODO The stuff has been rewritten using the chained list instead 
+// TODO The stuff was rewritten using the chained list instead 
 //      of the H table
 //      so we could remove the GroupHT from the gdcmParser
 // To be checked
@@ -1019,15 +1020,10 @@ void gdcmParser::WriteEntries(FileType type, FILE * _fp)
    //       TODO : find a trick (in STL?) to do it, at low cost !
 
    void *ptr;
-
-   // TODO : get grPixel and numPixel
-   guint16 grPixel =0x7fe0;
-   guint16 numPixel=0x0010;
-   //IterHT it = GetHeaderEntrySameNumber(grPixel,numPixel);
-   
-
+      
    // TODO (?) tester les echecs en ecriture (apres chaque fwrite)
-
+   int compte =0;
+   
    for (ListTag::iterator tag2=listEntries.begin();
         tag2 != listEntries.end();
         ++tag2)
@@ -1037,7 +1033,6 @@ void gdcmParser::WriteEntries(FileType type, FILE * _fp)
       lgr = (*tag2)->GetReadLength();
       val = (*tag2)->GetValue().c_str();
       vr =  (*tag2)->GetVR();
- cout << hex << gr << " " << el << "  " << vr <<" lgr " << lgr << endl;     
       if ( type == ACR ) 
       { 
          if (gr < 0x0008)   continue; // ignore pure DICOM V3 groups
@@ -1119,14 +1114,17 @@ void gdcmParser::WriteEntries(FileType type, FILE * _fp)
          }
          tokens.clear();
          continue;
-      }     
+      } 
+          
       // Pixels are never loaded in the element !
-      
-      // TODO : FIX --> doesn't work when ICONE is found !!!
-      
-      if ((gr == grPixel) && (el == numPixel) ) 
-         break;
-
+      // we stop writting when Pixel are processed
+      // FIX : we loose trailing elements (RAB, right now)           
+            
+      if ((gr == GrPixel) && (el == NumPixel) ) {
+         compte++;
+        if (compte == countGrPixel) // we passed *all* the GrPixel,NumPixel   
+            break;
+      }       
       fwrite ( val,(size_t)lgr ,(size_t)1 ,_fp); // Elem value
    }
 }
@@ -1240,8 +1238,8 @@ void gdcmParser::LoadHeaderEntries(void) {
       LoadEntryVoidArea(0x0028,0x1221);  // Segmented Red   Palette Color LUT Data
       LoadEntryVoidArea(0x0028,0x1222);  // Segmented Green Palette Color LUT Data
       LoadEntryVoidArea(0x0028,0x1223);  // Segmented Blue  Palette Color LUT Data
-   }
-
+   }   
+   
    // --------------------------------------------------------------
    // Special Patch to allow gdcm to read ACR-LibIDO formated images
    //
@@ -1400,11 +1398,11 @@ void gdcmParser::AddHeaderEntry(gdcmHeaderEntry *newHeaderEntry) {
    guint16 group   = Entry->GetGroup();
    std::string  vr = Entry->GetVR();
    guint16 length16;
-   if( (element == 0x0010) && (group == 0x7fe0) ) 
+   if( (element == NumPixel) && (group == GrPixel) ) 
    {
       dbg.SetDebug(-1);
       dbg.Verbose(2, "gdcmParser::FindLength: ",
-                     "we reached 7fe0 0010");
+                     "we reached (GrPixel,NumPixel)");
    }   
    
    if ( (filetype == ExplicitVR) && (! Entry->IsImplicitVR()) ) 
@@ -1742,19 +1740,25 @@ void gdcmParser::FixHeaderEntryFoundLength(gdcmHeaderEntry *Entry, guint32 Found
 {
    Entry->SetReadLength(FoundLength); // will be updated only if a bug is found
                     
-   if ( FoundLength == 0xffffffff) 
-   {
+   if ( FoundLength == 0xffffffff) {
       FoundLength = 0;
    }
+   
+   guint16 gr =Entry->GetGroup();
+   guint16 el =Entry->GetElement(); 
+     
+   if (FoundLength%2) {
+      std::cout << "Warning : Tag with uneven length " << FoundLength 
+          <<  "in x(" << hex << gr << "," << el <<")" << std::endl;
+   }
       
    // Sorry for the patch!  
    // XMedCom did the trick to read some nasty GE images ...
-   else if (FoundLength == 13) 
-   {
+   if (FoundLength == 13) {
       // The following 'if' will be removed when there is no more
       // images on Creatis HDs with a 13 length for Manufacturer...
       if ( (Entry->GetGroup() != 0x0008) ||  
-           ( (Entry->GetElement() != 0x0070) && (Entry->GetElement() != 0x0080) ) ) {
+           ( (Entry->GetElement() != 0x0070) && (Entry->GetElement() != 0x0080) ) ){
       // end of remove area
          FoundLength =10;
          Entry->SetReadLength(10); // a bug is to be fixed
@@ -1764,8 +1768,7 @@ void gdcmParser::FixHeaderEntryFoundLength(gdcmHeaderEntry *Entry, guint32 Found
    // to fix some garbage 'Leonardo' Siemens images
    // May be commented out to avoid overhead
    else if ( (Entry->GetGroup() == 0x0009) &&
-       ( (Entry->GetElement() == 0x1113) || (Entry->GetElement() == 0x1114) ) )
-   {
+       ( (Entry->GetElement() == 0x1113) || (Entry->GetElement() == 0x1114) ) ){
       FoundLength =4;
       Entry->SetReadLength(4); // a bug is to be fixed 
    } 
@@ -2018,6 +2021,15 @@ bool gdcmParser::CheckSwap() {
       // FIXME
       // Use gdcmParser::dicom_vr to test all the possibilities
       // instead of just checking for UL, OB and UI !?
+      
+      // FIXME : FIXME:
+      // Sometimes (see : gdcmData/icone.dcm) group 0x0002 *is* Explicit VR,
+      // but elem 0002,0010 (Transfert Syntax) tells us the file is *Implicit* VR.
+      // -and it is !- 
+      
+      // The following test is *absolutely useless*, since everything *goes right*
+      // with a *100 % wrong* assumption !!!
+      
       if( (memcmp(entCur, "UL", (size_t)2) == 0) ||
          (memcmp(entCur, "OB", (size_t)2) == 0) ||
          (memcmp(entCur, "UI", (size_t)2) == 0) )   
@@ -2299,7 +2311,6 @@ gdcmHeaderEntry *gdcmParser::ReadNextHeaderEntry(void) {
       return NULL;
    }
    NewEntry->SetOffset(ftell(fp));  
-   //if ( (g==0x7fe0) && (n==0x0010) ) 
    return NewEntry;
 }
 
index 74db3d233c6fd53d53f5360a01ef42217fbdb442..2ab4cce6eb2ab9339a89527729d2735e17807152 100644 (file)
@@ -98,6 +98,9 @@ public:
 
 // System access
    inline int GetSwapCode(void) { return sw; }
+   guint16 GetGrPixel(void) {return GrPixel;}
+   guint16 GetNumPixel(void) {return NumPixel;}
+   
    guint16 SwapShort(guint16);   // needed by gdcmFile
    guint32 SwapLong(guint32);    // needed by gdcmFile
    guint16 UnswapShort(guint16); // needed by gdcmFile
@@ -142,12 +145,19 @@ protected:
    static const unsigned int MAX_SIZE_PRINT_ELEMENT_VALUE;
 
 protected:
+   TagHeaderEntryHT tagHT; // H Table (multimap), to provide fast access
+   ListTag listEntries;    // chained list, to keep the 'spacial' ordering
+    
    int enableSequences;
    int printLevel;
    
-   TagHeaderEntryHT tagHT; // H Table (multimap), to provide fast access
-   ListTag listEntries;    // chained list, to keep the 'spacial' ordering 
-   
+   // For some ACR-NEMA images, it's *not* 7fe0, 0010 ...    
+   guint16 GrPixel;
+   guint16 NumPixel;
+   // some files may contain icons; GrPixel,NumPixel appears several times
+   // Let's remember how many times!
+   int countGrPixel;
+      
 private:
    // Read
    bool ParseHeader(bool exception_on_error = false) throw(gdcmFormatError);
@@ -227,7 +237,7 @@ private:
    // order no to polute the screen output. By default,
    // this upper bound is fixed to 64 bytes.   
    guint32 MaxSizePrintEntry;
-
+   
 };
 
 //-----------------------------------------------------------------------------