]> Creatis software - gdcm.git/blobdiff - src/gdcmFile.cxx
ENH: Afterall a Dashboard on Win32 is usefull :)
[gdcm.git] / src / gdcmFile.cxx
index a2ddfc70a88fad33cfa402db1f869fb346c057ff..8c3cb2796cfa1c0f98e232571c47caffcd74e807 100644 (file)
@@ -1,14 +1,14 @@
-/*=========================================================================
+  /*=========================================================================
                                                                                 
   Program:   gdcm
   Module:    $RCSfile: gdcmFile.cxx,v $
   Language:  C++
-  Date:      $Date: 2004/09/01 16:23:59 $
-  Version:   $Revision: 1.122 $
+  Date:      $Date: 2004/09/27 08:39:07 $
+  Version:   $Revision: 1.131 $
                                                                                 
   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
   l'Image). All rights reserved. See Doc/License.txt or
-  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.htm for details.
+  http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
                                                                                 
      This software is distributed WITHOUT ANY WARRANTY; without even
      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
@@ -38,26 +38,12 @@ typedef std::pair<TagDocEntryHT::iterator,TagDocEntryHT::iterator> IterHT;
  *        user sets an a posteriori shadow dictionary (efficiency can be
  *        seen as a side effect).   
  * @param header already built gdcmHeader
- * @return
  */
 gdcmFile::gdcmFile(gdcmHeader *header)
 {
    Header     = header;
    SelfHeader = false;
-   
-   PixelRead  = -1; // no ImageData read yet.
-   LastAllocatedPixelDataLength = 0;
-   PixelData = NULL;
-   
-   InitialSpp = "";     
-   InitialPhotInt = "";
-   InitialPlanConfig = "";
-   InitialBitsAllocated = "";
-       
-   if (Header->IsReadable())
-   {
-      SetPixelDataSizeFromHeader();
-   }
+   SaveInitialValues();
 }
 
 /**
@@ -79,36 +65,208 @@ gdcmFile::gdcmFile(std::string const & filename )
 {
    Header = new gdcmHeader( filename );
    SelfHeader = true;
-   
+   SaveInitialValues();
+}
+
+/**
+ * \ingroup   gdcmFile
+ * \brief canonical destructor
+ * \note  If the gdcmHeader was created by the gdcmFile constructor,
+ *        it is destroyed by the gdcmFile
+ */
+gdcmFile::~gdcmFile()
+{ 
+   if( SelfHeader )
+   {
+      delete Header;
+   }
+   Header = 0;
+
+   DeleteInitialValues();
+}
+
+/**
+ * \ingroup   gdcmFile
+ * \brief Sets some initial values for the Constructor
+ * \warning not end user intended
+ */
+void gdcmFile::SaveInitialValues()
+{ 
+
    PixelRead  = -1; // no ImageData read yet.
    LastAllocatedPixelDataLength = 0;
-   PixelData = NULL;
+   Pixel_Data = 0;
 
    InitialSpp = "";     
    InitialPhotInt = "";
    InitialPlanConfig = "";
    InitialBitsAllocated = "";
-           
+   InitialHighBit = "";
+  
+   InitialRedLUTDescr   = 0;
+   InitialGreenLUTDescr = 0;
+   InitialBlueLUTDescr  = 0;
+   InitialRedLUTData    = 0;
+   InitialGreenLUTData  = 0;
+   InitialBlueLUTData   = 0; 
+                
    if ( Header->IsReadable() )
    {
       SetPixelDataSizeFromHeader();
+      
+      // the following values *may* be modified 
+      // by gdcmFile::GetImageDataIntoVectorRaw
+      // we save their initial value.
+      InitialSpp           = Header->GetEntryByNumber(0x0028,0x0002);
+      InitialPhotInt       = Header->GetEntryByNumber(0x0028,0x0004);
+      InitialPlanConfig    = Header->GetEntryByNumber(0x0028,0x0006);
+      
+      InitialBitsAllocated = Header->GetEntryByNumber(0x0028,0x0100);
+      InitialHighBit       = Header->GetEntryByNumber(0x0028,0x0102);
+
+      // the following entries *may* be removed from the H table
+      // (NOT deleted ...) by gdcmFile::GetImageDataIntoVectorRaw  
+      // we keep a pointer on them.
+      InitialRedLUTDescr   = Header->GetDocEntryByNumber(0x0028,0x1101);
+      InitialGreenLUTDescr = Header->GetDocEntryByNumber(0x0028,0x1102);
+      InitialBlueLUTDescr  = Header->GetDocEntryByNumber(0x0028,0x1103);
+
+      InitialRedLUTData    = Header->GetDocEntryByNumber(0x0028,0x1201);
+      InitialGreenLUTData  = Header->GetDocEntryByNumber(0x0028,0x1202);
+      InitialBlueLUTData   = Header->GetDocEntryByNumber(0x0028,0x1203); 
    }
 }
 
 /**
  * \ingroup   gdcmFile
- * \brief canonical destructor
- * \note  If the gdcmHeader was created by the gdcmFile constructor,
- *        it is destroyed by the gdcmFile
+ * \brief restores some initial values
+ * \warning not end user intended
  */
-gdcmFile::~gdcmFile()
-{
-   if( SelfHeader )
+void gdcmFile::RestoreInitialValues()
+{   
+   if ( Header->IsReadable() )
+   {      
+      // the following values *may* have been modified 
+      // by gdcmFile::GetImageDataIntoVectorRaw
+      // we restore their initial value.
+      if ( InitialSpp != "")
+         Header->SetEntryByNumber(InitialSpp,0x0028,0x0002);
+      if ( InitialPhotInt != "")
+         Header->SetEntryByNumber(InitialPhotInt,0x0028,0x0004);
+      if ( InitialPlanConfig != "")
+
+         Header->SetEntryByNumber(InitialPlanConfig,0x0028,0x0006);
+      if ( InitialBitsAllocated != "")
+          Header->SetEntryByNumber(InitialBitsAllocated,0x0028,0x0100);
+      if ( InitialHighBit != "")
+          Header->SetEntryByNumber(InitialHighBit,0x0028,0x0102);
+               
+      // the following entries *may* be have been removed from the H table
+      // (NOT deleted ...) by gdcmFile::GetImageDataIntoVectorRaw  
+      // we restore them.
+
+      if (InitialRedLUTDescr)
+         Header->AddEntry(InitialRedLUTDescr);
+      if (InitialGreenLUTDescr)
+         Header->AddEntry(InitialGreenLUTDescr);
+      if (InitialBlueLUTDescr)
+         Header->AddEntry(InitialBlueLUTDescr);
+
+      if (InitialRedLUTData)
+         Header->AddEntry(InitialBlueLUTDescr);
+      if (InitialGreenLUTData)
+         Header->AddEntry(InitialGreenLUTData);
+      if (InitialBlueLUTData)
+         Header->AddEntry(InitialBlueLUTData);
+   }
+}
+
+/**
+ * \ingroup   gdcmFile
+ * \brief delete initial values (il they were saved)
+ *        of InitialLutDescriptors and InitialLutData
+ */
+void gdcmFile::DeleteInitialValues()
+{ 
+
+// InitialLutDescriptors and InitialLutData
+// will have to be deleted if the don't belong any longer
+// to the Header H table when the header is deleted...
+
+   if ( InitialRedLUTDescr )           
+      delete InitialRedLUTDescr;
+  
+   if ( InitialGreenLUTDescr )
+      delete InitialGreenLUTDescr;
+      
+   if ( InitialBlueLUTDescr )      
+      delete InitialBlueLUTDescr; 
+       
+   if ( InitialRedLUTData )      
+      delete InitialRedLUTData;
+   
+   if ( InitialGreenLUTData != NULL)
+      delete InitialGreenLUTData;
+      
+   if ( InitialBlueLUTData != NULL)      
+      delete InitialBlueLUTData;      
+}
+
+/**
+ * \ingroup   gdcmFile
+ * \brief drop palette related initial values -if any-
+ *        (InitialLutDescriptors and InitialLutData)
+ *        out of header, to make it consistent with the Pixel_Data
+ *        as it's loaded in memory
+ */
+
+//FIXME : Should be nice, if we could let it here.
+//        will be moved to PixelData class
+// Now, the job is done in gdcmHeader.cxx
+  
+ /*
+void gdcmFile::DropInitialValues()
+{ 
+   gdcmHeader* h=GetHeader();
+   if ( GetEntryByNumber(0x0028,0x0002).c_str()[0] == '3' )
    {
-      delete Header;
+      // if SamplesPerPixel = 3, sure we don't need any LUT !   
+      // Drop 0028|1101, 0028|1102, 0028|1103
+      // Drop 0028|1201, 0028|1202, 0028|1203
+
+      gdcmDocEntry* e = h->GetDocEntryByNumber(0x0028,0x01101);
+      if (e)
+      {
+         h->RemoveEntryNoDestroy(e);
+      }
+      e = h->GetDocEntryByNumber(0x0028,0x1102);
+      if (e)
+      {
+         h->RemoveEntryNoDestroy(e);
+      }
+      e = h->GetDocEntryByNumber(0x0028,0x1103);
+      if (e)
+      {
+         h->RemoveEntryNoDestroy(e);
+      }
+      e = h->GetDocEntryByNumber(0x0028,0x01201);
+      if (e)
+      {
+         h->RemoveEntryNoDestroy(e);
+      }
+      e = h->GetDocEntryByNumber(0x0028,0x1202);
+      if (e)
+      {
+         h->RemoveEntryNoDestroy(e);
+      }
+      e = h->GetDocEntryByNumber(0x0028,0x1203);
+      if (e)
+      {
+         h->RemoveEntryNoDestroy(e);
+      }
    }
-   Header = 0;
 }
+*/
 
 //-----------------------------------------------------------------------------
 // Print
@@ -122,6 +280,7 @@ gdcmFile::~gdcmFile()
  *            image(s) pixels (multiframes taken into account) 
  * \warning : it is NOT the group 7FE0 length
  *          (no interest for compressed images).
+ * \warning : not end user intended ?
  */
 void gdcmFile::SetPixelDataSizeFromHeader()
 {
@@ -167,7 +326,8 @@ void gdcmFile::SetPixelDataSizeFromHeader()
          nb =16;
       }
    }
-   ImageDataSize =  ImageDataSizeRaw = Header->GetXSize() * Header->GetYSize() 
+   ImageDataSize =
+   ImageDataSizeRaw = Header->GetXSize() * Header->GetYSize() 
                 * Header->GetZSize() * (nb/8) * Header->GetSamplesPerPixel();
    std::string str_PhotometricInterpretation = 
                              Header->GetEntryByNumber(0x0028,0x0004);
@@ -181,21 +341,6 @@ void gdcmFile::SetPixelDataSizeFromHeader()
    }
 }
 
-
-/**
- * \ingroup   gdcmFile
- * \brief     Returns the size (in bytes) of required memory to hold
- *            the pixel data represented in this file, if user DOESN'T want 
- *            to get RGB pixels image when it's stored as a PALETTE COLOR image
- *            -the (vtk) user is supposed to know how to deal with LUTs-  
- * \warning   to be used with GetImagePixelsRaw()
- * @return    The size of pixel data in bytes.
- */
-size_t gdcmFile::GetImageDataSizeRaw()
-{
-   return ImageDataSizeRaw;
-}
-
 /**
  * \ingroup gdcmFile
  * \brief   - Allocates necessary memory, 
@@ -207,27 +352,35 @@ size_t gdcmFile::GetImageDataSizeRaw()
  * @return  Pointer to newly allocated pixel data.
  *          NULL if alloc fails 
  */
-void *gdcmFile::GetImageData()
+uint8_t* gdcmFile::GetImageData()
 {
    // FIXME (Mathieu)
-   // I need to deallocate PixelData before doing any allocation:
+   // I need to deallocate Pixel_Data before doing any allocation:
    
-   if ( PixelData )
-      if ( LastAllocatedPixelDataLength != ImageDataSize)
-         free (PixelData);
-   PixelData = new uint8_t[ImageDataSize];
-   if ( PixelData )
+   if ( Pixel_Data )
+     if ( LastAllocatedPixelDataLength != ImageDataSize ) 
+        free(Pixel_Data);
+   if ( !Pixel_Data )
+      Pixel_Data = new uint8_t[ImageDataSize];
+    
+   if ( Pixel_Data )
    {
       LastAllocatedPixelDataLength = ImageDataSize;
-         
-      GetImageDataIntoVector(PixelData, ImageDataSize);
+
+      // we load the pixels (and transform grey level + LUT into RGB)
+      GetImageDataIntoVector(Pixel_Data, ImageDataSize);
+
+      // We say the value *is* loaded.
+      GetHeader()->SetEntryByNumber( GDCM_BINLOADED,
+         GetHeader()->GetGrPixel(), GetHeader()->GetNumPixel());
+
       // Will be 7fe0, 0010 in standard case
-      GetHeader()->SetEntryVoidAreaByNumber( PixelData, 
+      GetHeader()->SetEntryBinAreaByNumber( Pixel_Data, 
          GetHeader()->GetGrPixel(), GetHeader()->GetNumPixel()); 
    }      
    PixelRead = 0; // no PixelRaw
 
-   return PixelData;
+   return Pixel_Data;
 }
 
 /**
@@ -324,7 +477,7 @@ size_t gdcmFile::GetImageDataIntoVector (void* destination, size_t maxSize)
  * @return  Pointer to newly allocated pixel data.
  * \        NULL if alloc fails 
  */
-void * gdcmFile::GetImageDataRaw ()
+uint8_t* gdcmFile::GetImageDataRaw ()
 {
    size_t imgDataSize;
    if ( Header->HasLUT() )
@@ -334,24 +487,32 @@ void * gdcmFile::GetImageDataRaw ()
       imgDataSize = ImageDataSize;
     
    // FIXME (Mathieu)
-   // I need to deallocate PixelData before doing any allocation:
+   // I need to deallocate Pixel_Data before doing any allocation:
    
-   if ( PixelData )
-      if ( LastAllocatedPixelDataLength != imgDataSize)
-         free (PixelData);
-   PixelData = new uint8_t[imgDataSize];
-   if ( PixelData )
+   if ( Pixel_Data )
+      if ( LastAllocatedPixelDataLength != imgDataSize )
+         free(Pixel_Data);
+   if ( !Pixel_Data ) 
+      Pixel_Data = new uint8_t[imgDataSize];
+
+   if ( Pixel_Data )
    {
       LastAllocatedPixelDataLength = imgDataSize;
       
-      GetImageDataIntoVectorRaw(PixelData, imgDataSize);
+      // we load the pixels ( grey level or RGB, but NO transformation)
+       GetImageDataIntoVectorRaw(Pixel_Data, imgDataSize);
+
+      // We say the value *is* loaded.
+      GetHeader()->SetEntryByNumber( GDCM_BINLOADED,
+         GetHeader()->GetGrPixel(), GetHeader()->GetNumPixel());
       // will be 7fe0, 0010 in standard cases
-      GetHeader()->SetEntryVoidAreaByNumber(PixelData, 
-         GetHeader()->GetGrPixel(), GetHeader()->GetNumPixel()); 
+      GetHeader()->SetEntryBinAreaByNumber(Pixel_Data, 
+         GetHeader()->GetGrPixel(), GetHeader()->GetNumPixel());
    } 
    PixelRead = 1; // PixelRaw
 
-   return PixelData;
+   return Pixel_Data;
 }
 
 /**
@@ -378,7 +539,7 @@ void * gdcmFile::GetImageDataRaw ()
  * @return  On success, the number of bytes actually copied. Zero on
  *          failure e.g. MaxSize is lower than necessary.
  */
-size_t gdcmFile::GetImageDataIntoVectorRaw (void *destination, size_t maxSize)
+size_t gdcmFile::GetImageDataIntoVectorRaw (voiddestination, size_t maxSize)
 {
    int nb, nbu, highBit, sign;
 
@@ -386,21 +547,9 @@ size_t gdcmFile::GetImageDataIntoVectorRaw (void *destination, size_t maxSize)
   // in order to be able to restore the header in a disk-consistent state
   // (if user asks twice to get the pixels from disk)
 
-   if ( PixelRead == -1 ) // File was never "read" before
+   if ( PixelRead != -1 ) // File was "read" before
    {  
-      InitialSpp           = Header->GetEntryByNumber(0x0028,0x0002);
-      InitialPhotInt       = Header->GetEntryByNumber(0x0028,0x0004);
-      InitialPlanConfig    = Header->GetEntryByNumber(0x0028,0x0006);
-      InitialBitsAllocated = Header->GetEntryByNumber(0x0028,0x0100);
-   }
-   else // File was already "read", the following *may* have been modified
-        // we restore them to be in a disk-consistent state
-   {
-       // FIXME : What happened with the LUTs ?
-       Header->SetEntryByNumber(InitialSpp,0x0028,0x0002);
-       Header->SetEntryByNumber(InitialPhotInt,0x0028,0x0004);
-       Header->SetEntryByNumber(InitialPlanConfig,0x0028,0x0006);
-       Header->SetEntryByNumber(InitialBitsAllocated,0x0028,0x0100);   
+      RestoreInitialValues(); 
    }
    
    PixelRead = 1 ; // PixelRaw
@@ -516,14 +665,15 @@ size_t gdcmFile::GetImageDataIntoVectorRaw (void *destination, size_t maxSize)
          return 0;
       }
    }
-// DO NOT remove this code commented out.
-// Nobody knows what's expecting you ...
-// Just to 'see' what was actually read on disk :-(
-
-//   FILE * f2;
-//   f2 = fopen("SpuriousFile.RAW","wb");
-//   fwrite(destination,ImageDataSize,1,f2);
-//   fclose(f2);
+/// \todo
+/// DO NOT remove this code commented out.
+/// Nobody knows what's expecting you ...
+/// Just to 'see' what was actually read on disk :-(
+///
+///   FILE*  f2;
+///   f2 = fopen("SpuriousFile.RAW","wb");
+///   fwrite(destination,ImageDataSize,1,f2);
+///   fclose(f2);
 
    // Deal with the color
    // -------------------
@@ -640,20 +790,23 @@ size_t gdcmFile::GetImageDataIntoVectorRaw (void *destination, size_t maxSize)
    }
    // now, it's an RGB image
    // Lets's write it in the Header
+   // Droping Palette Color out of the Header
+   // has been moved to the Write process.
 
-   // CreateOrReplaceIfExist ?
+   // TODO : move 'values' modification to the write process
+   //      : save also (in order to be able to restore)
+   //      : 'high bit' -when not equal to 'bits stored' + 1
+   //      : 'bits allocated', when it's equal to 12 ?!
 
    std::string spp = "3";            // Samples Per Pixel
    std::string photInt = "RGB ";     // Photometric Interpretation
    std::string planConfig = "0";     // Planar Configuration
-
-
      
    Header->SetEntryByNumber(spp,0x0028,0x0002);
    Header->SetEntryByNumber(photInt,0x0028,0x0004);
    Header->SetEntryByNumber(planConfig,0x0028,0x0006);
  
-   /// \todo Drop Palette Color out of the Header? 
    return ImageDataSize; 
 }
 
@@ -669,11 +822,11 @@ size_t gdcmFile::GetImageDataIntoVectorRaw (void *destination, size_t maxSize)
  *
  * @return boolean
  */
-bool gdcmFile::SetImageData(void *inData, size_t expectedSize)
+bool gdcmFile::SetImageData(uint8_t* inData, size_t expectedSize)
 {
    Header->SetImageDataSize( expectedSize );
 // FIXME : if already allocated, memory leak !
-   PixelData     = inData;
+   Pixel_Data     = inData;
    ImageDataSize = ImageDataSizeRaw = expectedSize;
    PixelRead     = 1;
 // FIXME : 7fe0, 0010 IS NOT set ...
@@ -692,13 +845,13 @@ bool gdcmFile::SetImageData(void *inData, size_t expectedSize)
 
 bool gdcmFile::WriteRawData(std::string const & fileName)
 {
-   FILE *fp1 = fopen(fileName.c_str(), "wb");
+   FILEfp1 = fopen(fileName.c_str(), "wb");
    if (fp1 == NULL)
    {
       printf("Fail to open (write) file [%s] \n", fileName.c_str());
       return false;
    }
-   fwrite (PixelData, ImageDataSize, 1, fp1);
+   fwrite (Pixel_Data, ImageDataSize, 1, fp1);
    fclose (fp1);
 
    return true;
@@ -771,7 +924,7 @@ bool gdcmFile::WriteBase (std::string const & fileName, FileType type)
       return false;
    }
 
-   FILE *fp1 = fopen(fileName.c_str(), "wb");
+   FILEfp1 = fopen(fileName.c_str(), "wb");
    if (fp1 == NULL)
    {
       printf("Failed to open (write) File [%s] \n", fileName.c_str());
@@ -842,7 +995,7 @@ bool gdcmFile::WriteBase (std::string const & fileName, FileType type)
    }
    // ----------------- End of Special Patch ----------------
    
-   // fwrite(PixelData, ImageDataSize, 1, fp1);  // should be useless, now
+   // fwrite(Pixel_Data, ImageDataSize, 1, fp1);  // should be useless, now
    fclose (fp1);
 
    return true;
@@ -859,7 +1012,7 @@ bool gdcmFile::WriteBase (std::string const & fileName, FileType type)
  * @param   lgr Area Length
  * @param   nb Pixels Bit number 
  */
-void gdcmFile::SwapZone(void *im, int swap, int lgr, int nb)
+void gdcmFile::SwapZone(voidim, int swap, int lgr, int nb)
 {
    int i;
 
@@ -941,9 +1094,9 @@ void gdcmFile::SwapZone(void *im, int swap, int lgr, int nb)
  * @param   destination where the pixel data should be stored.
  *
  */
-bool gdcmFile::ReadPixelData(void *destination) 
+bool gdcmFile::ReadPixelData(voiddestination) 
 {
-   FILE *fp = Header->OpenFile();
+   FILEfp = Header->OpenFile();
 
    if ( !fp )
    {