]> Creatis software - gdcm.git/blobdiff - src/gdcmFileHelper.cxx
We are no longer cheated by Elem belonging to group 0x0002,
[gdcm.git] / src / gdcmFileHelper.cxx
index 62c0374010cd07b5e0f043fa57d3fac6ba34b8e8..2f54d3edc9579bb3a11f6306b7c40f93bdee9894 100644 (file)
@@ -4,8 +4,8 @@
   Module:    $RCSfile: gdcmFileHelper.cxx,v $
   Language:  C++
 
-  Date:      $Date: 2006/05/30 08:14:50 $
-  Version:   $Revision: 1.104 $
+  Date:      $Date: 2007/07/26 08:36:49 $
+  Version:   $Revision: 1.119 $
                                                                                 
   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
   l'Image). All rights reserved. See Doc/License.txt or
@@ -51,18 +51,19 @@ gdcm::File *f = new gdcm::File(fileName);
 // user may also decide he doesn't want to load some parts of the header
 gdcm::File *f = new gdcm::File();
 f->SetFileName(fileName);
-   f->SetLoadMode(LD_NOSEQ);             // or      
-   f->SetLoadMode(LD_NOSHADOW);          // or
+   f->SetLoadMode(LD_NOSEQ);               // or      
+   f->SetLoadMode(LD_NOSHADOW);            // or
    f->SetLoadMode(LD_NOSEQ | LD_NOSHADOW); // or
    f->SetLoadMode(LD_NOSHADOWSEQ);
 f->Load();
 
+// To decide whether it's an 'image of interest for him, or not,
 // user can now check some values
 std::string v = f->GetEntryValue(groupNb,ElementNb);
 
 // to get the pixels, user needs a gdcm::FileHelper
 gdcm::FileHelper *fh = new gdcm::FileHelper(f);
-// user may ask not to convert Palette to RGB
+// user may ask not to convert Palette (if any) to RGB
 uint8_t *pixels = fh->GetImageDataRaw();
 int imageLength = fh->GetImageDataRawSize();
 // He can now use the pixels, create a new image, ...
@@ -72,8 +73,11 @@ To re-write the image, user re-uses the gdcm::FileHelper
 
 fh->SetImageData( userPixels, userPixelsLength);
 fh->SetTypeToRaw(); // Even if it was possible to convert Palette to RGB
-                     // (WriteMode is set)
+                    // (WriteMode is set)
+
+// If user wants to write the file as MONOCHROME1 (0=white)
+fh->SetPhotometricInterpretationToMonochrome1();
+
 fh->SetWriteTypeToDcmExpl();  // he wants Explicit Value Representation
                               // Little Endian is the default
                               // no other value is allowed
@@ -91,33 +95,58 @@ These lines will be moved to the document-to-be 'Developer's Guide'
 
 WriteMode : WMODE_RAW / WMODE_RGB
 WriteType : ImplicitVR, ExplicitVR, ACR, ACR_LIBIDO
+PhotometricInterpretation : MONOCHROME2 (0=black), MONOCHROME2 (0=white)
+
+
+fh->SetWriteMode(WMODE_RAW / WMODE_RGB)
 
-fh1->Write(newFileName);
-   SetWriteFileTypeToImplicitVR() / SetWriteFileTypeToExplicitVR();
-   (modifies TransferSyntax)
+fh->SetWriteType( ImplicitVR/ExplicitVR/ACR/ACR_LIBIDO/JPEG/JPEG2000)
+      
+fh->Write(newFileName);
+   CheckMandatoryElements(); // Checks existing ones / Add missing ones
+   Fix VR if unknown elements
+   SetWriteFileTypeToImplicitVR() / SetWriteFileTypeToExplicitVR(); /
+   SetWriteFileTypeToACR() / SetWriteFileTypeToJPEG() / SetWriteFileTypeToJ2K()
+      (Modifies TransferSyntax if any; Pushes to the Archives old one)
    SetWriteToRaw(); / SetWriteToRGB();
-      (modifies, when necessary : photochromatic interpretation, 
-         samples per pixel, Planar configuration, 
-         bits allocated, bits stored, high bit -ACR 24 bits-
-         Pixels element VR, pushes out the LUT )
+      (Modifies and pushes to the Archive, when necessary : photochr. interp., 
+       samples per pixel, Planar configuration, 
+       bits allocated, bits stored, high bit -ACR 24 bits-
+       Pixels element VR, pushes out the LUT )
+          SetWriteToRaw()
+             Sets Photometric Interpretation
+             DataEntry *pixel =CopyDataEntry(7fe0,0010,VR)
+             Sets VR, BinArea, Length for PixelData
+             if MONOCHROME1
+                ConvertFixGreyLevels
+             Archive->Push(photInt);
+             Archive->Push(pixel);
+             photInt->Delete();
+             pixel->Delete();
+        SetWriteToRGB()
+           if NumberOfScalarComponents==1
+              SetWriteToRaw(); return;
+           PixelReadConverter->BuildRGBImage()
+           DataEntry *pixel =CopyDataEntry(7fe0,0010,VR)
+           Archives spp, planConfig,photInt, pixel
+           Pushes out any LUT               
    CheckWriteIntegrity();
       (checks user given pixels length)
    FileInternal->Write(fileName,WriteType)
-   fp = opens file(fileName);
-   ComputeGroup0002Length( );
-   BitsAllocated 12->16
-      RemoveEntry(palettes, etc)
+      fp = opens file(fileName); // out|binary
+      ComputeGroup0002Length( );
       Document::WriteContent(fp, writetype);
+         writes Dicom File Preamble not ACR-NEMA
+         ElementSet::WriteContent(fp, writetype);
+            writes recursively all DataElements    
    RestoreWrite();
-      (moves back to the File all the archived elements)
-   RestoreWriteFileType();
-      (pushes back group 0002, with TransferSyntax)
+         (moves back to the gdcm::File all the archived elements)
 */
 
 
 
 
-namespace gdcm 
+namespace GDCM_NAME_SPACE 
 {
 typedef std::map<uint16_t, int> GroupHT;    //  Hash Table
 //-------------------------------------------------------------------------
@@ -230,8 +259,8 @@ bool FileHelper::Load()
 }
 
 /**
- * \brief   Accesses an existing DataEntry through it's (group, element) 
- *          and modifies it's content with the given value.
+ * \brief   Accesses an existing DataEntry through its (group, element) 
+ *          and modifies its content with the given value.
  * @param   content new value (string) to substitute with
  * @param   group  group number of the Dicom Element to modify
  * @param   elem element number of the Dicom Element to modify
@@ -245,8 +274,8 @@ bool FileHelper::SetEntryString(std::string const &content,
 
 
 /**
- * \brief   Accesses an existing DataEntry through it's (group, element) 
- *          and modifies it's content with the given value.
+ * \brief   Accesses an existing DataEntry through its (group, element) 
+ *          and modifies its content with the given value.
  * @param   content new value (void*  -> uint8_t*) to substitute with
  * @param   lgth new value length
  * @param   group  group number of the Dicom Element to modify
@@ -265,6 +294,7 @@ bool FileHelper::SetEntryBinArea(uint8_t *content, int lgth,
  * @param   content (string) value to be set
  * @param   group   Group number of the Entry 
  * @param   elem  Element number of the Entry
+ * @param   vr  Value Representation of the DataElement to be inserted
  * \return  pointer to the modified/created DataEntry (NULL when creation
  *          failed).
  */ 
@@ -279,10 +309,11 @@ DataEntry *FileHelper::InsertEntryString(std::string const &content,
  * \brief   Modifies the value of a given DataEntry when it exists.
  *          Creates it with the given value when unexistant.
  *          A copy of the binArea is made to be kept in the Document.
- * @param   binArea (binary)value to be set
+ * @param   binArea (binary) value to be set
  * @param   lgth new value length
  * @param   group   Group number of the Entry 
  * @param   elem  Element number of the Entry
+ * @param   vr  Value Representation of the DataElement to be inserted 
  * \return  pointer to the modified/created DataEntry (NULL when creation
  *          failed).
  */
@@ -469,7 +500,7 @@ size_t FileHelper::GetImageDataIntoVector (void *destination, size_t maxSize)
  */
 void FileHelper::SetImageData(uint8_t *inData, size_t expectedSize)
 {
-   SetUserData(inData, expectedSize);
+   PixelWriteConverter->SetUserData(inData, expectedSize);
 }
 
 /**
@@ -482,7 +513,18 @@ void FileHelper::SetImageData(uint8_t *inData, size_t expectedSize)
  */
 void FileHelper::SetUserData(uint8_t *inData, size_t expectedSize)
 {
-   PixelWriteConverter->SetUserData(inData, expectedSize);
+   if( WriteType == JPEG2000 )
+   {
+      PixelWriteConverter->SetCompressJPEG2000UserData(inData, expectedSize, FileInternal);
+   }
+   else if( WriteType == JPEG )
+   {
+      PixelWriteConverter->SetCompressJPEGUserData(inData, expectedSize, FileInternal);
+   }
+   else
+   {
+      PixelWriteConverter->SetUserData(inData, expectedSize);
+   }
 }
 
 /**
@@ -665,7 +707,6 @@ bool FileHelper::WriteAcr (std::string const &fileName)
  */
 bool FileHelper::Write(std::string const &fileName)
 {
-
    CheckMandatoryElements(); //called once, here !
    
    bool flag = false;
@@ -687,12 +728,15 @@ bool FileHelper::Write(std::string const &fileName)
    // Let's just *dream* about it; *never* trust a user !
    // We turn to Implicit VR if at least the VR of one element is unknown.
    
+   // Better we let DocEntry::WriteContent to put vr=UN for undocumented Shadow Groups !
+
+/*
          e = FileInternal->GetFirstEntry();
          while (e != 0)
          {
             if (e->GetVR() == "  ")  
             {
+
                SetWriteTypeToDcmImplVR();
                SetWriteFileTypeToImplicitVR();
                flag = true;
@@ -706,8 +750,10 @@ bool FileHelper::Write(std::string const &fileName)
             SetWriteFileTypeToExplicitVR();
          }
          break;
+*/
+
+         SetWriteFileTypeToExplicitVR();
 
-         SetWriteFileTypeToExplicitVR(); // to see JPRx
   break;
       case ACR:
       case ACR_LIBIDO:
@@ -728,8 +774,12 @@ bool FileHelper::Write(std::string const &fileName)
       case JPEG:
          SetWriteFileTypeToJPEG();
          break;
+
+      case JPEG2000:
+         SetWriteFileTypeToJPEG2000();
+         break;
    }
+
    // --------------------------------------------------------------
    // Special Patch to allow gdcm to re-write ACR-LibIDO formated images
    //
@@ -760,16 +810,17 @@ bool FileHelper::Write(std::string const &fileName)
    }
 
    bool check = CheckWriteIntegrity(); // verifies length
-   if (WriteType == JPEG ) check = true;
+   if (WriteType == JPEG || WriteType == JPEG2000) 
+      check = true;
+
    if (check)
    {
       check = FileInternal->Write(fileName,WriteType);
    }
 
-   RestoreWrite(); 
+   RestoreWrite();
   // RestoreWriteFileType();
   // RestoreWriteMandatory();
-   
 
    // --------------------------------------------------------------
    // Special Patch to allow gdcm to re-write ACR-LibIDO formated images
@@ -785,11 +836,7 @@ bool FileHelper::Write(std::string const &fileName)
 //-----------------------------------------------------------------------------
 // Protected
 /**
- * \brief Checks the write integrity
- *
- * The tests made are :
- *  - verify the size of the image to write with the possible write
- *    when the user set an image data
+ * \brief Verifies the size of the user given PixelData
  * @return true if check is successfull
  */
 bool FileHelper::CheckWriteIntegrity()
@@ -837,7 +884,6 @@ bool FileHelper::CheckWriteIntegrity()
             break;
       }
    }
-
    return true;
 }
 
@@ -845,6 +891,8 @@ bool FileHelper::CheckWriteIntegrity()
  * \brief Updates the File to write RAW data (as opposed to RGB data)
  *       (modifies, when necessary, photochromatic interpretation, 
  *       bits allocated, Pixels element VR)
+ *       WARNING : if SetPhotometricInterpretationToMonochrome1() was called
+ *                 before Pixel Elements if modified :-( 
  */ 
 void FileHelper::SetWriteToRaw()
 {
@@ -855,16 +903,20 @@ void FileHelper::SetWriteToRaw()
    } 
    else
    {
+      // 0x0028,0x0004 : Photometric Interpretation
       DataEntry *photInt = CopyDataEntry(0x0028,0x0004,"CS");
       if (FileInternal->HasLUT() )
       {
          photInt->SetString("PALETTE COLOR ");
       }
       else
-      {
-         photInt->SetString("MONOCHROME2 ");
+      {     
+         if (GetPhotometricInterpretation() == 2)
+            photInt->SetString("MONOCHROME2 ");  // 0 = Black
+         else
+            photInt->SetString("MONOCHROME1 ");  // 0 = White !
       }
-
+    
       PixelWriteConverter->SetReadData(PixelReadConverter->GetRaw(),
                                        PixelReadConverter->GetRawSize());
 
@@ -873,11 +925,22 @@ void FileHelper::SetWriteToRaw()
          vr = "OW";
       if ( FileInternal->GetBitsAllocated()==24 ) // For RGB ACR files 
          vr = "OB";
+       // For non RAW data. Mainly JPEG
+      if( WriteType == JPEG || WriteType == JPEG2000)
+      {
+         vr = "OW";
+      }
+      
       DataEntry *pixel = 
          CopyDataEntry(GetFile()->GetGrPixel(),GetFile()->GetNumPixel(),vr);
       pixel->SetFlag(DataEntry::FLAG_PIXELDATA);
       pixel->SetBinArea(PixelWriteConverter->GetData(),false);
       pixel->SetLength(PixelWriteConverter->GetDataSize());
+     
+      if (!FileInternal->HasLUT() && GetPhotometricInterpretation() == 1)
+      {
+          ConvertFixGreyLevels( pixel->GetBinArea(), pixel->GetLength() );
+      }      
 
       Archive->Push(photInt);
       Archive->Push(pixel);
@@ -986,7 +1049,6 @@ void FileHelper::SetWriteToRGB()
  */ 
 void FileHelper::RestoreWrite()
 {
-
    Archive->Restore(0x0028,0x0002);
    Archive->Restore(0x0028,0x0004);
    
@@ -1044,13 +1106,28 @@ void FileHelper::SetWriteFileTypeToACR()
    Archive->Push(0x0002,0x0102);
 }
 
+/**
+ * \brief Sets in the File the TransferSyntax to 'JPEG2000'
+ */
+void FileHelper::SetWriteFileTypeToJPEG2000()
+{
+   std::string ts = Util::DicomString(
+   Global::GetTS()->GetSpecialTransferSyntax(TS::JPEG2000Lossless) );
+
+   DataEntry *tss = CopyDataEntry(0x0002,0x0010,"UI");
+   tss->SetString(ts);
+
+   Archive->Push(tss);
+   tss->Delete();   
+}
+
 /**
  * \brief Sets in the File the TransferSyntax to 'JPEG'
- */ 
+ */
 void FileHelper::SetWriteFileTypeToJPEG()
 {
-   std::string ts = Util::DicomString( 
-      Global::GetTS()->GetSpecialTransferSyntax(TS::JPEGBaselineProcess1) );
+   std::string ts = Util::DicomString(
+      Global::GetTS()->GetSpecialTransferSyntax(TS::JPEGLosslessProcess14_1) );
 
    DataEntry *tss = CopyDataEntry(0x0002,0x0010,"UI");
    tss->SetString(ts);
@@ -1087,14 +1164,6 @@ void FileHelper::SetWriteFileTypeToImplicitVR()
    tss->Delete();
 }
 
-
-/**
- * \brief Restore in the File the initial group 0002
- */ 
-void FileHelper::RestoreWriteFileType()
-{
-}
-
 /**
  * \brief Set the Write not to Libido format
  */ 
@@ -1106,9 +1175,6 @@ void FileHelper::SetWriteToLibido()
    if ( oldRow && oldCol )
    {
       std::string rows, columns; 
-
-      //DataEntry *newRow=DataEntry::New(oldRow->GetDictEntry());
-      //DataEntry *newCol=DataEntry::New(oldCol->GetDictEntry());
       
       DataEntry *newRow=DataEntry::New(0x0028, 0x0010, "US");
       DataEntry *newCol=DataEntry::New(0x0028, 0x0011, "US");
@@ -1185,7 +1251,6 @@ DataEntry *FileHelper::CopyDataEntry(uint16_t group, uint16_t elem,
 
    if ( oldE )
    {
-      //newE = DataEntry::New(oldE->GetDictEntry());
       newE = DataEntry::New(group, elem, vr);
       newE->Copy(oldE);
    }
@@ -1243,9 +1308,9 @@ We have to deal with 4 *very* different cases :
    FILTERED_IMAGE
 -3) user created a new image, using a set of existing images (eg MIP, MPR, cartography image)
    CREATED_IMAGE
--4) user modified/added some tags *without processing* the pixels (anonymization..
+-4) user modified/added some tags *without processing* the pixels (anonymization...)
    UNMODIFIED_PIXELS_IMAGE
--Probabely some more to be added  
+-Probabely some more to be added.  
  
 gdcm::FileHelper::CheckMandatoryElements() deals automatically with these cases.
 
@@ -1382,15 +1447,20 @@ void FileHelper::CheckMandatoryElements()
   
    //0002 0000 UL 1 Meta Group Length
    //0002 0001 OB 1 File Meta Information Version
-   //0002 0002 UI 1 Media Stored SOP Class UID
-   //0002 0003 UI 1 Media Stored SOP Instance UID
+   //0002 0002 UI 1 Media Storage SOP Class UID
+   //0002 0003 UI 1 Media Storage SOP Instance UID
    //0002 0010 UI 1 Transfer Syntax UID
    //0002 0012 UI 1 Implementation Class UID
    //0002 0013 SH 1 Implementation Version Name
    //0002 0016 AE 1 Source Application Entity Title
    //0002 0100 UI 1 Private Information Creator
    //0002 0102 OB 1 Private Information
-  
+
+   // Push out 'ACR-NEMA-special' entries, if any
+      Archive->Push(0x0008,0x0001); // Length to End
+      Archive->Push(0x0008,0x0010); // Recognition Code
+      Archive->Push(0x0028,0x0005); // Image Dimension
+
    // Create them if not found
    // Always modify the value
    // Push the entries to the archive.
@@ -1523,7 +1593,8 @@ void FileHelper::CheckMandatoryElements()
    std::ostringstream s;
    // check 'Bits Allocated' vs decent values
    int nbBitsAllocated = FileInternal->GetBitsAllocated();
-   if ( nbBitsAllocated == 0 || nbBitsAllocated > 32)
+   if ( nbBitsAllocated == 0 || nbBitsAllocated > 32 
+      || ( nbBitsAllocated > 8 && nbBitsAllocated <16) )
    {
       CopyMandatoryEntry(0x0028,0x0100,"16","US");
       gdcmWarningMacro("(0028,0100) changed from "
@@ -1556,6 +1627,24 @@ void FileHelper::CheckMandatoryElements()
                        << " for consistency purpose");
    }
 
+   // check Pixel Representation (default it as 0 -unsigned-)
+   
+   DataEntry *e_0028_0103 = FileInternal->GetDataEntry(0x0028, 0x0103);
+   if ( !e_0028_0103 )
+   {
+      gdcmWarningMacro("PixelRepresentation (0028,0103) is supposed to be mandatory");
+      CopyMandatoryEntry(0x0028, 0x0103,"0","US"); 
+   }
+   else
+   {
+      int sign = (int)e_0028_0103->GetValue(0);
+      if (sign !=1 && sign !=0)
+      {
+         gdcmWarningMacro("PixelRepresentation (0028,0103) is supposed to be =1 or =0");
+         CopyMandatoryEntry(0x0028, 0x0103,"0","US");
+      }
+   }
+
    std::string pixelSpacing = FileInternal->GetEntryString(0x0028,0x0030);
    if ( pixelSpacing == GDCM_UNFOUND )
    {
@@ -1571,8 +1660,6 @@ void FileHelper::CheckMandatoryElements()
    //         an imager (see also 0008,0x0064)          
       CheckMandatoryEntry(0x0018,0x1164,pixelSpacing,"DS");
 
-
-
 /*
 ///Exact meaning of RETired fields
 
@@ -1616,17 +1703,17 @@ is only from (0020,0030) and (0020,0035)
       CopyMandatoryEntry(0x0020, 0x0032,imagePositionRet,"DS");
       Archive->Push(0x0020,0x0030); 
       CopyMandatoryEntry(0x0020, 0x0037,imageOrientationRet,"DS");
-      Archive->Push(0x0020,0x0035);        
-   }        
+      Archive->Push(0x0020,0x0035);
+   }
 */
-    
+
    // Samples Per Pixel (type 1) : default to grayscale 
    CheckMandatoryEntry(0x0028,0x0002,"1","US");
 
    // --- Check UID-related Entries ---
  
    // At the end, not to overwrite the original ones,
-   // needed by 'Referenced SOP Instance UID', 'Referenced SOP Class UID'   
+   // needed by 'Referenced SOP Instance UID', 'Referenced SOP Class UID'
    // 'SOP Instance UID'  
    CopyMandatoryEntry(0x0008,0x0018,sop,"UI");
 
@@ -1638,7 +1725,7 @@ is only from (0020,0030) and (0020,0035)
        // See PS 3.3, Page 408
    
        // DV = Digitized Video
-       // DI = Digital Interface   
+       // DI = Digital Interface 
        // DF = Digitized Film
        // WSD = Workstation
        // SD = Scanned Document
@@ -1655,7 +1742,7 @@ is only from (0020,0030) and (0020,0035)
    
    }
 */
-           
+  
    // ---- The user will never have to take any action on the following ----
 
    // new value for 'SOP Instance UID'
@@ -1664,7 +1751,7 @@ is only from (0020,0030) and (0020,0035)
    // Instance Creation Date
    const std::string &date = Util::GetCurrentDate();
    CopyMandatoryEntry(0x0008,0x0012,date,"DA");
+
    // Instance Creation Time
    const std::string &time = Util::GetCurrentTime();
    CopyMandatoryEntry(0x0008,0x0013,time,"TM");
@@ -1712,15 +1799,15 @@ is only from (0020,0030) and (0020,0035)
 
    // Instance Number
    CheckMandatoryEntry(0x0020,0x0013,"","IS");
-   
+
    // Patient Orientation
    // Can be computed from (0020|0037) :  Image Orientation (Patient)
-   gdcm::Orientation *o = gdcm::Orientation::New();
+   GDCM_NAME_SPACE::Orientation *o = GDCM_NAME_SPACE::Orientation::New();
    std::string ori = o->GetOrientation ( FileInternal );
    o->Delete();
    if (ori != "\\" && ori != GDCM_UNFOUND)
       CheckMandatoryEntry(0x0020,0x0020,ori,"CS");
-   else   
+   else
       CheckMandatoryEntry(0x0020,0x0020,"","CS");
 
    // Default Patient Position to HFS
@@ -1767,8 +1854,12 @@ is only from (0020,0030) and (0020,0035)
       CheckMandatoryEntry(it->first, 0x0000, "0"); 
   }    
   // Third stage : update all 'zero level' groups length
-*/ 
+*/
+
 
+   if (PhotometricInterpretation == 1)
+   {
+   }
 } 
 
 void FileHelper::CheckMandatoryEntry(uint16_t group,uint16_t elem,std::string value,const VRKey &vr )
@@ -1839,7 +1930,6 @@ void FileHelper::RestoreWriteMandatory()
    Archive->Restore(0x0020,0x000e);
 }
 
-
 /**
  * \brief   CallStartMethod
  */
@@ -1876,9 +1966,11 @@ void FileHelper::Initialize()
 {
    UserFunction = 0;
    ContentType = USER_OWN_IMAGE;
-   
+
    WriteMode = WMODE_RAW;
    WriteType = ExplicitVR;
+   
+   PhotometricInterpretation = 2; // Black = 0
 
    PixelReadConverter  = new PixelReadConvert;
    PixelWriteConverter = new PixelWriteConvert;
@@ -1914,9 +2006,95 @@ uint8_t *FileHelper::GetRaw()
    return raw;
 }
 
+/**
+ * \brief Deal with Grey levels i.e. re-arange them
+ *        to have low values = dark, high values = bright
+ */
+void FileHelper::ConvertFixGreyLevels(uint8_t *raw, size_t rawSize)
+{
+   uint32_t i; // to please M$VC6
+   int16_t j;
+
+   // Number of Bits Allocated for storing a Pixel is defaulted to 16
+   // when absent from the file.
+   int bitsAllocated = FileInternal->GetBitsAllocated();
+   if ( bitsAllocated == 0 )
+   {
+      bitsAllocated = 16;
+   }
+
+   else if (bitsAllocated > 8 && bitsAllocated < 16 && bitsAllocated != 12)
+   {
+      bitsAllocated = 16;
+   }   
+   // Number of "Bits Stored", defaulted to number of "Bits Allocated"
+   // when absent from the file.
+   int bitsStored = FileInternal->GetBitsStored();
+   if ( bitsStored == 0 )
+   {
+      bitsStored = bitsAllocated;
+   }
+
+   if (!FileInternal->IsSignedPixelData())
+   {
+      if ( bitsAllocated == 8 )
+      {
+         uint8_t *deb = (uint8_t *)raw;
+         for (i=0; i<rawSize; i++)      
+         {
+            *deb = 255 - *deb;
+            deb++;
+         }
+         return;
+      }
+
+      if ( bitsAllocated == 16 )
+      {
+         uint16_t mask =1;
+         for (j=0; j<bitsStored-1; j++)
+         {
+            mask = (mask << 1) +1; // will be fff when BitsStored=12
+         }
+
+         uint16_t *deb = (uint16_t *)raw;
+         for (i=0; i<rawSize/2; i++)      
+         {
+            *deb = mask - *deb;
+            deb++;
+         }
+         return;
+       }
+   }
+   else
+   {
+      if ( bitsAllocated == 8 )
+      {
+         uint8_t smask8 = 255;
+         uint8_t *deb = (uint8_t *)raw;
+         for (i=0; i<rawSize; i++)      
+         {
+            *deb = smask8 - *deb;
+            deb++;
+         }
+         return;
+      }
+      if ( bitsAllocated == 16 )
+      {
+         uint16_t smask16 = 65535;
+         uint16_t *deb = (uint16_t *)raw;
+         for (i=0; i<rawSize/2; i++)      
+         {
+            *deb = smask16 - *deb;
+            deb++;
+         }
+         return;
+      }
+   }
+}
+
 //-----------------------------------------------------------------------------
 /**
- * \brief   Prints the common part of DataEntry, SeqEntry
+ * \brief   Prints the FileInternal + info on PixelReadConvertor
  * @param   os ostream we want to print in
  * @param indent (unused)
  */
@@ -1934,3 +2112,153 @@ void FileHelper::Print(std::ostream &os, std::string const &)
 
 //-----------------------------------------------------------------------------
 } // end namespace gdcm
+
+
+/* Probabely something to be added to use Rescale Slope/Intercept
+Have a look ,at ITK code !
+
+// Internal function to rescale pixel according to Rescale Slope/Intercept
+template<class TBuffer, class TSource>
+void RescaleFunction(TBuffer* buffer, TSource *source,
+                     double slope, double intercept, size_t size)
+{
+  size /= sizeof(TSource);
+
+  if (slope != 1.0 && intercept != 0.0)
+    {
+    // Duff's device.  Instead of this code:
+    //
+    //   for(unsigned int i=0; i<size; i++)
+    //    {
+    //    buffer[i] = (TBuffer)(source[i]*slope + intercept);
+    //    }
+    //
+    // use Duff's device which exploits "fall through"
+    register size_t n = (size + 7) / 8;
+    switch ( size % 8)
+      {
+      case 0: do { *buffer++ = (TBuffer)((*source++)*slope + intercept);
+      case 7:      *buffer++ = (TBuffer)((*source++)*slope + intercept);
+      case 6:      *buffer++ = (TBuffer)((*source++)*slope + intercept);
+      case 5:      *buffer++ = (TBuffer)((*source++)*slope + intercept);
+      case 4:      *buffer++ = (TBuffer)((*source++)*slope + intercept);
+      case 3:      *buffer++ = (TBuffer)((*source++)*slope + intercept);
+      case 2:      *buffer++ = (TBuffer)((*source++)*slope + intercept);
+      case 1:      *buffer++ = (TBuffer)((*source++)*slope + intercept);
+                 }  while (--n > 0);
+      }
+    }
+  else if (slope == 1.0 && intercept != 0.0)
+    {
+    // Duff's device.  Instead of this code:
+    //
+    //   for(unsigned int i=0; i<size; i++)
+    //    {
+    //    buffer[i] = (TBuffer)(source[i] + intercept);
+    //    }
+    //
+    // use Duff's device which exploits "fall through"
+    register size_t n = (size + 7) / 8;
+    switch ( size % 8)
+      {
+      case 0: do { *buffer++ = (TBuffer)(*source++ + intercept);
+      case 7:      *buffer++ = (TBuffer)(*source++ + intercept);
+      case 6:      *buffer++ = (TBuffer)(*source++ + intercept);
+      case 5:      *buffer++ = (TBuffer)(*source++ + intercept);
+      case 4:      *buffer++ = (TBuffer)(*source++ + intercept);
+      case 3:      *buffer++ = (TBuffer)(*source++ + intercept);
+      case 2:      *buffer++ = (TBuffer)(*source++ + intercept);
+      case 1:      *buffer++ = (TBuffer)(*source++ + intercept);
+                 }  while (--n > 0);
+      }
+    }
+  else if (slope != 1.0 && intercept == 0.0)
+    {
+    // Duff's device.  Instead of this code:
+    //
+    //   for(unsigned int i=0; i<size; i++)
+    //    {
+    //    buffer[i] = (TBuffer)(source[i]*slope);
+    //    }
+    //
+    // use Duff's device which exploits "fall through"
+    register size_t n = (size + 7) / 8;
+    switch ( size % 8)
+      {
+      case 0: do { *buffer++ = (TBuffer)((*source++)*slope);
+      case 7:      *buffer++ = (TBuffer)((*source++)*slope);
+      case 6:      *buffer++ = (TBuffer)((*source++)*slope);
+      case 5:      *buffer++ = (TBuffer)((*source++)*slope);
+      case 4:      *buffer++ = (TBuffer)((*source++)*slope);
+      case 3:      *buffer++ = (TBuffer)((*source++)*slope);
+      case 2:      *buffer++ = (TBuffer)((*source++)*slope);
+      case 1:      *buffer++ = (TBuffer)((*source++)*slope);
+                 }  while (--n > 0);
+      }
+    }
+  else
+    {
+    // Duff's device.  Instead of this code:
+    //
+    //   for(unsigned int i=0; i<size; i++)
+    //    {
+    //    buffer[i] = (TBuffer)(source[i]);
+    //    }
+    //
+    // use Duff's device which exploits "fall through"
+    register size_t n = (size + 7) / 8;
+    switch ( size % 8)
+      {
+      case 0: do { *buffer++ = (TBuffer)(*source++);
+      case 7:      *buffer++ = (TBuffer)(*source++);
+      case 6:      *buffer++ = (TBuffer)(*source++);
+      case 5:      *buffer++ = (TBuffer)(*source++);
+      case 4:      *buffer++ = (TBuffer)(*source++);
+      case 3:      *buffer++ = (TBuffer)(*source++);
+      case 2:      *buffer++ = (TBuffer)(*source++);
+      case 1:      *buffer++ = (TBuffer)(*source++);
+                 }  while (--n > 0);
+      }
+   }   
+}
+
+
+template<class TSource>
+void RescaleFunction(ImageIOBase::IOComponentType bufferType,
+                     void* buffer, TSource *source,
+                     double slope, double intercept, size_t size)
+{
+  switch (bufferType)
+    {
+    case ImageIOBase::UCHAR:
+      RescaleFunction( (unsigned char *)buffer, source, slope, intercept, size);
+      break;
+    case ImageIOBase::CHAR:
+      RescaleFunction( (char *)buffer, source, slope, intercept, size);
+      break;
+    case ImageIOBase::USHORT:
+      RescaleFunction( (unsigned short *)buffer, source, slope, intercept,size);
+      break;
+    case ImageIOBase::SHORT:
+      RescaleFunction( (short *)buffer, source, slope, intercept, size);
+      break;
+    case ImageIOBase::UINT:
+      RescaleFunction( (unsigned int *)buffer, source, slope, intercept, size);
+      break;
+    case ImageIOBase::INT:
+      RescaleFunction( (int *)buffer, source, slope, intercept, size);
+      break;
+    case ImageIOBase::FLOAT:
+      RescaleFunction( (float *)buffer, source, slope, intercept, size);
+      break;
+    case ImageIOBase::DOUBLE:
+      RescaleFunction( (double *)buffer, source, slope, intercept, size);
+      break;
+    default:
+      ::itk::OStringStream message;
+      message << "itk::ERROR: GDCMImageIO: Unknown component type : " << bufferType;
+      ::itk::ExceptionObject e(__FILE__, __LINE__, message.str().c_str(),ITK_LOCATION);
+      throw e;
+    }
+}
+*/