]> Creatis software - gdcm.git/blobdiff - src/gdcmFile.cxx
ENH: I am a moron. Fix compilation of gdcm in static mode, I had to add some new...
[gdcm.git] / src / gdcmFile.cxx
index 62051158b1acc18cb5bebfd277f9a013b749acb1..6b9138b2ad26ea1e6d59b624994fc358ef04e202 100644 (file)
@@ -3,8 +3,8 @@
   Program:   gdcm
   Module:    $RCSfile: gdcmFile.cxx,v $
   Language:  C++
-  Date:      $Date: 2004/09/29 17:33:17 $
-  Version:   $Revision: 1.132 $
+  Date:      $Date: 2004/10/01 12:40:57 $
+  Version:   $Revision: 1.134 $
                                                                                 
   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
   l'Image). All rights reserved. See Doc/License.txt or
@@ -519,66 +519,17 @@ size_t gdcmFile::GetImageDataIntoVectorRaw (void* destination, size_t maxSize)
 
    bool signedPixel = Header->IsSignedPixelData();
 
-// SPLIT ME
-////////////////////////////////////////////////////////
-// ENDIANITY SECTION: re-arange bytes inside the integer
-   if ( numberBitsAllocated != 8 )
-   {
-      SwapZone( destination, Header->GetSwapCode(), ImageDataSize,
-                numberBitsAllocated );
-   }
-     
-   // to avoid pb with some xmedcon breakers images 
-   if (  ( numberBitsAllocated == 16 )
-      && ( numberBitsStored < numberBitsAllocated )
-      && ( ! signedPixel ) )
-   {
-      int l = (int)(ImageDataSize / (numberBitsAllocated/8));
-      uint16_t *deb = (uint16_t *)destination;
-      for(int i = 0; i<l; i++)
-      {
-         if( *deb == 0xffff )
-         {
-           *deb = 0;
-         }
-         deb++;   
-      }
-   }
+   ConvertReorderEndianity( (uint8_t*) destination,
+                            ImageDataSize,
+                            numberBitsStored,
+                            numberBitsAllocated,
+                            signedPixel );
 
-// SPLIT ME
-//////////////////////////////////
-// re arange bits inside the bytes
-   if ( numberBitsStored != numberBitsAllocated )
-   {
-      int l = (int)(ImageDataSize / (numberBitsAllocated/8));
-      if ( numberBitsAllocated == 16 )
-      {
-         uint16_t mask = 0xffff;
-         mask = mask >> ( numberBitsAllocated - numberBitsStored );
-         uint16_t *deb = (uint16_t *)destination;
-         for(int i = 0; i<l; i++)
-         {
-            *deb = (*deb >> (numberBitsStored - highBitPosition - 1)) & mask;
-            deb++;
-         }
-      }
-      else if ( numberBitsAllocated == 32 )
-      {
-         uint32_t mask = 0xffffffff;
-         mask         = mask >> ( numberBitsAllocated - numberBitsStored );
-         uint32_t *deb = (uint32_t *)destination;
-         for(int i = 0; i<l; i++)
-         {
-            *deb = (*deb >> (numberBitsStored - highBitPosition - 1)) & mask;
-            deb++;
-         }
-      }
-      else
-      {
-         dbg.Verbose(0, "gdcmFile::GetImageDataIntoVector: weird image");
-         return 0;
-      }
-   }
+   ConvertReArrangeBits( (uint8_t*) destination,
+                         ImageDataSize,
+                         numberBitsStored,
+                         numberBitsAllocated,
+                         highBitPosition );
 
 #ifdef GDCM_DEBUG
    FILE*  DebugFile;
@@ -608,98 +559,36 @@ size_t gdcmFile::GetImageDataIntoVectorRaw (void* destination, size_t maxSize)
    //                            PhotometricInterpretation=PALETTE COLOR
    // and heuristic has to be found :-( 
 
-   int planConf = Header->GetPlanarConfiguration();  // 0028,0006
+   int planConf = Header->GetPlanarConfiguration();
 
-   // Whatever Planar Configuration is, 
-   // "PALETTE COLOR " implies that we deal with the palette. 
-   if ( Header->IsPaletteColor() )
+   // Planar configuration = 2 ==> 1 gray Plane + 3 LUT
+   //   ...and...
+   // whatever the Planar Configuration might be, "PALETTE COLOR "
+   // implies that we deal with the palette. 
+   if ( ( planConf == 2 ) || Header->IsPaletteColor() )
    {
-      planConf = 2;
+      return ImageDataSize;
    }
 
-   switch ( planConf )
-   {
-      case 0:
-         // Pixels are already RGB
-         break;
-      case 1:
-         if ( Header->IsYBRFull() )
-         {
-            // Warning : YBR_FULL_422 acts as RGB
-            //         : we need to make RGB Pixels from Planes Y,cB,cR
-
-            // to see the tricks about YBR_FULL, YBR_FULL_422, 
-            // YBR_PARTIAL_422, YBR_ICT, YBR_RCT have a look at :
-            // ftp://medical.nema.org/medical/dicom/final/sup61_ft.pdf
-            // and be *very* affraid
-            //
-            int l        = Header->GetXSize() * Header->GetYSize();
-            int nbFrames = Header->GetZSize();
-
-            uint8_t* newDest = new uint8_t[ImageDataSize];
-            uint8_t* x       = newDest;
-            uint8_t* a       = (uint8_t*)destination;
-            uint8_t* b       = a + l;
-            uint8_t* c       = b + l;
-            double R,G,B;
-
-            /// \todo : Replace by the 'well known' integer computation
-            /// counterpart
-            /// see http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
-            /// for code optimisation
-    
-            for (int i = 0; i < nbFrames; i++)
-            {
-               for (int j = 0; j < l; j++)
-               {
-                  R = 1.164 *(*a-16) + 1.596 *(*c -128) + 0.5;
-                  G = 1.164 *(*a-16) - 0.813 *(*c -128) - 0.392 *(*b -128) + 0.5;
-                  B = 1.164 *(*a-16) + 2.017 *(*b -128) + 0.5;
-
-                  if (R < 0.0)   R = 0.0;
-                  if (G < 0.0)   G = 0.0;
-                  if (B < 0.0)   B = 0.0;
-                  if (R > 255.0) R = 255.0;
-                  if (G > 255.0) G = 255.0;
-                  if (B > 255.0) B = 255.0;
-
-                  *(x++) = (uint8_t)R;
-                  *(x++) = (uint8_t)G;
-                  *(x++) = (uint8_t)B;
-                  a++; b++; c++;  
-               }
-            }
-            memmove(destination, newDest, ImageDataSize);
-            delete[] newDest;
-         }
-         else
-         {
-            // need to make RGB Pixels from R,G,B Planes
-            // (all the Frames at a time)
+   // When planConf is 0, pixels are allready in RGB
 
-            int l = Header->GetXSize() * Header->GetYSize() * Header->GetZSize();
-
-            uint8_t *newDest = new uint8_t[ImageDataSize];
-            uint8_t *x       = newDest;
-            uint8_t *a       = (uint8_t *)destination;
-            uint8_t *b       = a + l;
-            uint8_t *c       = b + l;
-
-            for (int j = 0; j < l; j++)
-            {
-               *(x++) = *(a++);
-               *(x++) = *(b++);
-               *(x++) = *(c++);
-            }
-            memmove(destination, newDest, ImageDataSize);
-            delete[] newDest;
-         }
-         break;
-      case 2:                      
-         // Palettes were found
-         // Let the user deal with them !
-         return ImageDataSize;
+   if ( planConf == 1 )
+   {
+      uint8_t* newDest = new uint8_t[ImageDataSize];
+      // Warning : YBR_FULL_422 acts as RGB
+      if ( Header->IsYBRFull() )
+      {
+         ConvertYcBcRPlanesToRGBPixels((uint8_t*)destination, newDest);
+      }
+      else
+      {
+         ConvertRGBPlanesToRGBPixels((uint8_t*)destination, newDest);
+      }
+      memmove(destination, newDest, ImageDataSize);
+      delete[] newDest;
    }
+
+///////////////////////////////////////////////////
    // now, it's an RGB image
    // Lets's write it in the Header
  
@@ -722,6 +611,154 @@ size_t gdcmFile::GetImageDataIntoVectorRaw (void* destination, size_t maxSize)
    return ImageDataSize; 
 }
 
+/**
+ * \brief   Re-arrange the bits within the bytes.
+ */
+void gdcmFile::ConvertReArrangeBits( uint8_t* pixelZone,
+                                     size_t imageDataSize,
+                                     int numberBitsStored,
+                                     int numberBitsAllocated,
+                                     int highBitPosition)
+     throw ( gdcmFormatError )
+{
+   if ( numberBitsStored != numberBitsAllocated )
+   {
+      int l = (int)(imageDataSize / (numberBitsAllocated/8));
+      if ( numberBitsAllocated == 16 )
+      {
+         uint16_t mask = 0xffff;
+         mask = mask >> ( numberBitsAllocated - numberBitsStored );
+         uint16_t* deb = (uint16_t*)pixelZone;
+         for(int i = 0; i<l; i++)
+         {
+            *deb = (*deb >> (numberBitsStored - highBitPosition - 1)) & mask;
+            deb++;
+         }
+      }
+      else if ( numberBitsAllocated == 32 )
+      {
+         uint32_t mask = 0xffffffff;
+         mask = mask >> ( numberBitsAllocated - numberBitsStored );
+         uint32_t* deb = (uint32_t*)pixelZone;
+         for(int i = 0; i<l; i++)
+         {
+            *deb = (*deb >> (numberBitsStored - highBitPosition - 1)) & mask;
+            deb++;
+         }
+      }
+      else
+      {
+         dbg.Verbose(0, "gdcmFile::ConvertReArrangeBits: weird image");
+         throw gdcmFormatError( "gdcmFile::ConvertReArrangeBits()",
+                                "weird image !?" );
+      }
+   }
+}
+
+/**
+ * \brief Deal with endianity i.e. re-arange bytes inside the integer
+ */
+void gdcmFile::ConvertReorderEndianity( uint8_t* pixelZone,
+                                        size_t imageDataSize,
+                                        int numberBitsStored,
+                                        int numberBitsAllocated,
+                                        bool signedPixel)
+{
+   if ( numberBitsAllocated != 8 )
+   {
+      SwapZone( pixelZone, Header->GetSwapCode(), ImageDataSize,
+                numberBitsAllocated );
+   }
+     
+   // Special kludge in order to deal with xmedcon broken images:
+   if (  ( numberBitsAllocated == 16 )
+      && ( numberBitsStored < numberBitsAllocated )
+      && ( ! signedPixel ) )
+   {
+      int l = (int)(ImageDataSize / (numberBitsAllocated/8));
+      uint16_t *deb = (uint16_t *)pixelZone;
+      for(int i = 0; i<l; i++)
+      {
+         if( *deb == 0xffff )
+         {
+           *deb = 0;
+         }
+         deb++;   
+      }
+   }
+}
+
+/**
+ * \brief   Convert (Y plane, cB plane, cR plane) to RGB pixels
+ * \warning Works on all the frames at a time
+ */
+void gdcmFile::ConvertYcBcRPlanesToRGBPixels(uint8_t* source,
+                                             uint8_t* destination)
+{
+   // to see the tricks about YBR_FULL, YBR_FULL_422, 
+   // YBR_PARTIAL_422, YBR_ICT, YBR_RCT have a look at :
+   // ftp://medical.nema.org/medical/dicom/final/sup61_ft.pdf
+   // and be *very* affraid
+   //
+   int l        = Header->GetXSize() * Header->GetYSize();
+   int nbFrames = Header->GetZSize();
+
+   uint8_t* a = source;
+   uint8_t* b = source + l;
+   uint8_t* c = source + l + l;
+   double R, G, B;
+
+   /// \todo : Replace by the 'well known' integer computation
+   ///         counterpart. Refer to
+   ///            http://lestourtereaux.free.fr/papers/data/yuvrgb.pdf
+   ///         for code optimisation.
+   for (int i = 0; i < nbFrames; i++)
+   {
+      for (int j = 0; j < l; j++)
+      {
+         R = 1.164 *(*a-16) + 1.596 *(*c -128) + 0.5;
+         G = 1.164 *(*a-16) - 0.813 *(*c -128) - 0.392 *(*b -128) + 0.5;
+         B = 1.164 *(*a-16) + 2.017 *(*b -128) + 0.5;
+
+         if (R < 0.0)   R = 0.0;
+         if (G < 0.0)   G = 0.0;
+         if (B < 0.0)   B = 0.0;
+         if (R > 255.0) R = 255.0;
+         if (G > 255.0) G = 255.0;
+         if (B > 255.0) B = 255.0;
+
+         *(destination++) = (uint8_t)R;
+         *(destination++) = (uint8_t)G;
+         *(destination++) = (uint8_t)B;
+         a++;
+         b++;
+         c++;  
+      }
+   }
+}
+
+/**
+ * \brief   Convert (Red plane, Green plane, Blue plane) to RGB pixels
+ * \warning Works on all the frames at a time
+ */
+void gdcmFile::ConvertRGBPlanesToRGBPixels(uint8_t* source,
+                                           uint8_t* destination)
+{
+   int l = Header->GetXSize() * Header->GetYSize() * Header->GetZSize();
+
+   uint8_t* a = source;
+   uint8_t* b = source + l;
+   uint8_t* c = source + l + l;
+
+   for (int j = 0; j < l; j++)
+   {
+      *(destination++) = *(a++);
+      *(destination++) = *(b++);
+      *(destination++) = *(c++);
+   }
+}
+
 /**
  * \brief   Points the internal Pixel_Data pointer to the callers inData
  *          image representation, BUT WITHOUT COPYING THE DATA.
@@ -1014,32 +1051,12 @@ bool gdcmFile::ReadPixelData(void* destination)
       return false;
    }
 
-   // ----------------------  Compacted File (12 Bits Per Pixel)
-   // unpack 12 Bits pixels into 16 Bits pixels
-   // 2 pixels 12bit =     [0xABCDEF]
-   // 2 pixels 16bit = [0x0ABD] + [0x0FCE]
-   
    if ( Header->GetBitsAllocated() == 12 )
    {
-      int nbPixels = Header->GetXSize() * Header->GetYSize();
-      uint8_t b0, b1, b2;
-      
-      uint16_t* pdestination = (uint16_t*)destination;    
-      for(int p = 0; p < nbPixels; p += 2 )
-      {
-         fread(&b0,1,1,fp);
-         fread(&b1,1,1,fp);
-         fread(&b2,1,1,fp);      
-
-         //Two steps is necessary to please VC++
-         *pdestination++ =  ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f);
-         //                     A                     B                 D
-         *pdestination++ =  ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4);
-         //                     F                     C                 E
-  
-         // Troubles expected on Big-Endian processors ?
-      }
-
+      ConvertDecompress12BitsTo16Bits( (uint8_t*)destination, 
+                                       Header->GetXSize(),
+                                       Header->GetYSize(),
+                                       fp);
       Header->CloseFile();
       return true;
    }
@@ -1072,22 +1089,13 @@ bool gdcmFile::ReadPixelData(void* destination)
    }  
     
    // --------------- SingleFrame/Multiframe JPEG Lossless/Lossy/2000 
-   int nb;
-   std::string str_nb = Header->GetEntryByNumber(0x0028,0x0100);
-   if ( str_nb == GDCM_UNFOUND )
-   {
-      nb = 16;
-   }
-   else
+   int numberBitsAllocated = Header->GetBitsAllocated();
+   if ( ( numberBitsAllocated == 0 ) || ( numberBitsAllocated == 12 ) )
    {
-      nb = atoi( str_nb.c_str() );
-      if ( nb == 12 )
-      {
-         nb = 16;  // ?? 12 should be ACR-NEMA only
-      }
+      numberBitsAllocated = 16;
    }
 
-   int nBytes= nb/8;
+   int nBytes= numberBitsAllocated/8;
    int taille = Header->GetXSize() * Header->GetYSize()  
                 * Header->GetSamplesPerPixel();
    long fragmentBegining; // for ftell, fseek
@@ -1200,4 +1208,57 @@ bool gdcmFile::ReadPixelData(void* destination)
    Header->CloseFile();
    return res;
 }
+
+/**
+ * \brief Read from file a 12 bits per pixel image and uncompress it
+ *        into a 16 bits per pixel image.
+ */
+void gdcmFile::ConvertDecompress12BitsTo16Bits(
+                  uint8_t* pixelZone,
+                  int sizeX,
+                  int sizeY,
+                  FILE* filePtr)
+               throw ( gdcmFormatError )
+{
+   int nbPixels = sizeX * sizeY;
+   uint16_t* destination = (uint16_t*)pixelZone;    
+
+   for( int p = 0; p < nbPixels; p += 2 )
+   {
+      uint8_t b0, b1, b2;
+      size_t ItemRead;
+
+      ItemRead = fread( &b0, 1, 1, filePtr);
+      if ( ItemRead != 1 )
+      {
+         throw gdcmFormatError( "gdcmFile::ConvertDecompress12BitsTo16Bits()",
+                                "Unfound first block" );
+      }
+
+      ItemRead = fread( &b1, 1, 1, filePtr);
+      if ( ItemRead != 1 )
+      {
+         throw gdcmFormatError( "gdcmFile::ConvertDecompress12BitsTo16Bits()",
+                                "Unfound second block" );
+      }
+
+      ItemRead = fread( &b2, 1, 1, filePtr);      
+      if ( ItemRead != 1 )
+      {
+         throw gdcmFormatError( "gdcmFile::ConvertDecompress12BitsTo16Bits()",
+                                "Unfound second block" );
+      }
+
+      // Two steps are necessary to please VC++
+      //
+      // 2 pixels 12bit =     [0xABCDEF]
+      // 2 pixels 16bit = [0x0ABD] + [0x0FCE]
+      //                     A                     B                 D
+      *destination++ =  ((b0 >> 4) << 8) + ((b0 & 0x0f) << 4) + (b1 & 0x0f);
+      //                     F                     C                 E
+      *destination++ =  ((b2 & 0x0f) << 8) + ((b1 >> 4) << 4) + (b2 >> 4);
+  
+      /// \todo JPR Troubles expected on Big-Endian processors ?
+   }
+}
 //-----------------------------------------------------------------------------