]> Creatis software - gdcm.git/blobdiff - src/gdcmFileHelper.cxx
Forget to comment out InTag
[gdcm.git] / src / gdcmFileHelper.cxx
index 371a1567bc859a41990792b67bb0f4004d2bec84..62c0374010cd07b5e0f043fa57d3fac6ba34b8e8 100644 (file)
@@ -4,8 +4,8 @@
   Module:    $RCSfile: gdcmFileHelper.cxx,v $
   Language:  C++
 
   Module:    $RCSfile: gdcmFileHelper.cxx,v $
   Language:  C++
 
-  Date:      $Date: 2006/01/27 10:01:34 $
-  Version:   $Revision: 1.89 $
+  Date:      $Date: 2006/05/30 08:14:50 $
+  Version:   $Revision: 1.104 $
                                                                                 
   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
   l'Image). All rights reserved. See Doc/License.txt or
                                                                                 
   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
   l'Image). All rights reserved. See Doc/License.txt or
 #include "gdcmSeqEntry.h"
 #include "gdcmSQItem.h"
 #include "gdcmDataEntry.h"
 #include "gdcmSeqEntry.h"
 #include "gdcmSQItem.h"
 #include "gdcmDataEntry.h"
+#include "gdcmDocEntry.h"
 #include "gdcmFile.h"
 #include "gdcmPixelReadConvert.h"
 #include "gdcmPixelWriteConvert.h"
 #include "gdcmDocEntryArchive.h"
 #include "gdcmDictSet.h"
 #include "gdcmOrientation.h"
 #include "gdcmFile.h"
 #include "gdcmPixelReadConvert.h"
 #include "gdcmPixelWriteConvert.h"
 #include "gdcmDocEntryArchive.h"
 #include "gdcmDictSet.h"
 #include "gdcmOrientation.h"
-
 #if defined(__BORLANDC__)
    #include <mem.h> // for memset
 #endif 
 #if defined(__BORLANDC__)
    #include <mem.h> // for memset
 #endif 
@@ -73,7 +74,7 @@ fh->SetImageData( userPixels, userPixelsLength);
 fh->SetTypeToRaw(); // Even if it was possible to convert Palette to RGB
                      // (WriteMode is set)
  
 fh->SetTypeToRaw(); // Even if it was possible to convert Palette to RGB
                      // (WriteMode is set)
  
-fh->SetWriteTypeToDcmExpl(); // he wants Explicit Value Representation
+fh->SetWriteTypeToDcmExpl();  // he wants Explicit Value Representation
                               // Little Endian is the default
                               // no other value is allowed
                                 (-->SetWriteType(ExplicitVR);)
                               // Little Endian is the default
                               // no other value is allowed
                                 (-->SetWriteType(ExplicitVR);)
@@ -237,7 +238,7 @@ bool FileHelper::Load()
  * \return  false if DataEntry not found
  */
 bool FileHelper::SetEntryString(std::string const &content,
  * \return  false if DataEntry not found
  */
 bool FileHelper::SetEntryString(std::string const &content,
-                                    uint16_t group, uint16_t elem)
+                                uint16_t group, uint16_t elem)
 { 
    return FileInternal->SetEntryString(content, group, elem);
 }
 { 
    return FileInternal->SetEntryString(content, group, elem);
 }
@@ -253,7 +254,7 @@ bool FileHelper::SetEntryString(std::string const &content,
  * \return  false if DataEntry not found
  */
 bool FileHelper::SetEntryBinArea(uint8_t *content, int lgth,
  * \return  false if DataEntry not found
  */
 bool FileHelper::SetEntryBinArea(uint8_t *content, int lgth,
-                                     uint16_t group, uint16_t elem)
+                                 uint16_t group, uint16_t elem)
 {
    return FileInternal->SetEntryBinArea(content, lgth, group, elem);
 }
 {
    return FileInternal->SetEntryBinArea(content, lgth, group, elem);
 }
@@ -268,9 +269,10 @@ bool FileHelper::SetEntryBinArea(uint8_t *content, int lgth,
  *          failed).
  */ 
 DataEntry *FileHelper::InsertEntryString(std::string const &content,
  *          failed).
  */ 
 DataEntry *FileHelper::InsertEntryString(std::string const &content,
-                                                uint16_t group, uint16_t elem)
+                                         uint16_t group, uint16_t elem,
+                                         VRKey const &vr )
 {
 {
-   return FileInternal->InsertEntryString(content, group, elem);
+   return FileInternal->InsertEntryString(content, group, elem, vr);
 }
 
 /**
 }
 
 /**
@@ -285,9 +287,10 @@ DataEntry *FileHelper::InsertEntryString(std::string const &content,
  *          failed).
  */
 DataEntry *FileHelper::InsertEntryBinArea(uint8_t *binArea, int lgth,
  *          failed).
  */
 DataEntry *FileHelper::InsertEntryBinArea(uint8_t *binArea, int lgth,
-                                                 uint16_t group, uint16_t elem)
+                                          uint16_t group, uint16_t elem,
+                                          VRKey const &vr )
 {
 {
-   return FileInternal->InsertEntryBinArea(binArea, lgth, group, elem);
+   return FileInternal->InsertEntryBinArea(binArea, lgth, group, elem, vr);
 }
 
 /**
 }
 
 /**
@@ -381,16 +384,16 @@ uint8_t *FileHelper::GetImageData()
  *          - DOES NOT transform Grey plane + 3 Palettes into a RGB Plane
  * @return  Pointer to newly allocated pixel data.
  *          (uint8_t is just for prototyping. feel free to cast)
  *          - DOES NOT transform Grey plane + 3 Palettes into a RGB Plane
  * @return  Pointer to newly allocated pixel data.
  *          (uint8_t is just for prototyping. feel free to cast)
- *          NULL if alloc fails 
+ *          NULL if alloc fails
  */
 uint8_t *FileHelper::GetImageDataRaw ()
 {
    return GetRaw();
 }
 
  */
 uint8_t *FileHelper::GetImageDataRaw ()
 {
    return GetRaw();
 }
 
-#ifndef GDCM_LEGACY_REMOVE
+//#ifndef GDCM_LEGACY_REMOVE
 /*
 /*
- * \ brief   Useless function, since PixelReadConverter forces us 
+ * \brief   Useless function, since PixelReadConverter forces us 
  *          copy the Pixels anyway.  
  *          Reads the pixels from disk (uncompress if necessary),
  *          Transforms YBR pixels, if any, into RGB pixels
  *          copy the Pixels anyway.  
  *          Reads the pixels from disk (uncompress if necessary),
  *          Transforms YBR pixels, if any, into RGB pixels
@@ -398,7 +401,7 @@ uint8_t *FileHelper::GetImageDataRaw ()
  *          Transforms single Grey plane + 3 Palettes into a RGB Plane   
  *          Copies at most MaxSize bytes of pixel data to caller allocated
  *          memory space.
  *          Transforms single Grey plane + 3 Palettes into a RGB Plane   
  *          Copies at most MaxSize bytes of pixel data to caller allocated
  *          memory space.
- * \ warning This function allows people that want to build a volume
+ * \warning This function allows people that want to build a volume
  *          from an image stack *not to* have, first to get the image pixels, 
  *          and then move them to the volume area.
  *          It's absolutely useless for any VTK user since vtk chooses 
  *          from an image stack *not to* have, first to get the image pixels, 
  *          and then move them to the volume area.
  *          It's absolutely useless for any VTK user since vtk chooses 
@@ -407,14 +410,15 @@ uint8_t *FileHelper::GetImageDataRaw ()
  *          to load the image line by line, starting from the end.
  *          VTK users have to call GetImageData
  *     
  *          to load the image line by line, starting from the end.
  *          VTK users have to call GetImageData
  *     
- * @ param   destination Address (in caller's memory space) at which the
+ * @param   destination Address (in caller's memory space) at which the
  *          pixel data should be copied
  *          pixel data should be copied
- * @ param   maxSize Maximum number of bytes to be copied. When MaxSize
+ * @param   maxSize Maximum number of bytes to be copied. When MaxSize
  *          is not sufficient to hold the pixel data the copy is not
  *          executed (i.e. no partial copy).
  *          is not sufficient to hold the pixel data the copy is not
  *          executed (i.e. no partial copy).
- * @ return  On success, the number of bytes actually copied. Zero on
+ * @return  On success, the number of bytes actually copied. Zero on
  *          failure e.g. MaxSize is lower than necessary.
  */
  *          failure e.g. MaxSize is lower than necessary.
  */
+ /*
 size_t FileHelper::GetImageDataIntoVector (void *destination, size_t maxSize)
 {
    if ( ! GetRaw() )
 size_t FileHelper::GetImageDataIntoVector (void *destination, size_t maxSize)
 {
    if ( ! GetRaw() )
@@ -447,7 +451,8 @@ size_t FileHelper::GetImageDataIntoVector (void *destination, size_t maxSize)
            PixelReadConverter->GetRawSize() );
    return PixelReadConverter->GetRawSize();
 }
            PixelReadConverter->GetRawSize() );
    return PixelReadConverter->GetRawSize();
 }
-#endif
+*/
+//#endif
 
 /**
  * \brief   Points the internal pointer to the callers inData
 
 /**
  * \brief   Points the internal pointer to the callers inData
@@ -660,15 +665,50 @@ bool FileHelper::WriteAcr (std::string const &fileName)
  */
 bool FileHelper::Write(std::string const &fileName)
 {
  */
 bool FileHelper::Write(std::string const &fileName)
 {
+
+   CheckMandatoryElements(); //called once, here !
+   
+   bool flag = false;
+   DocEntry *e;   
    switch(WriteType)
    {
       case ImplicitVR:
          SetWriteFileTypeToImplicitVR();
          break;
    switch(WriteType)
    {
       case ImplicitVR:
          SetWriteFileTypeToImplicitVR();
          break;
       case Unknown:  // should never happen; ExplicitVR is the default value
       case ExplicitVR:
       case Unknown:  // should never happen; ExplicitVR is the default value
       case ExplicitVR:
-         SetWriteFileTypeToExplicitVR();
+
+   // User should ask gdcm to write an image in Explicit VR mode
+   // only when he is sure *all* the VR of *all* the DataElements is known.
+   // i.e : when there are *only* Public Groups
+   // or *all* the Shadow Groups are fully described in the relevant Shadow
+   // Dictionnary
+   // 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.
+   
+         e = FileInternal->GetFirstEntry();
+         while (e != 0)
+         {
+            if (e->GetVR() == "  ")  
+            {
+               SetWriteTypeToDcmImplVR();
+               SetWriteFileTypeToImplicitVR();
+               flag = true;
+               break;         
+            } 
+            e = FileInternal->GetNextEntry();
+         }        
+
+         if (!flag)
+         {
+            SetWriteFileTypeToExplicitVR();
+         }
          break;
          break;
+
+         SetWriteFileTypeToExplicitVR(); // to see JPRx
+  break;
       case ACR:
       case ACR_LIBIDO:
       // NOTHING is done here just for LibIDO.
       case ACR:
       case ACR_LIBIDO:
       // NOTHING is done here just for LibIDO.
@@ -678,17 +718,18 @@ bool FileHelper::Write(std::string const &fileName)
       // (shame on him !)
       // We add Recognition Code (RET)
         if ( ! FileInternal->GetDataEntry(0x0008, 0x0010) )
       // (shame on him !)
       // We add Recognition Code (RET)
         if ( ! FileInternal->GetDataEntry(0x0008, 0x0010) )
-            FileInternal->InsertEntryString("ACR-NEMA V1.0 ", 0x0008, 0x0010);
+            FileInternal->InsertEntryString("ACR-NEMA V1.0 ", 
+                                             0x0008, 0x0010, "LO");
          SetWriteFileTypeToACR();
         // SetWriteFileTypeToImplicitVR(); // ACR IS implicit VR !
          break;
          SetWriteFileTypeToACR();
         // SetWriteFileTypeToImplicitVR(); // ACR IS implicit VR !
          break;
+      /// \todo FIXME : JPEG may be either ExplicitVR or ImplicitVR
       case JPEG:
          SetWriteFileTypeToJPEG();
       case JPEG:
          SetWriteFileTypeToJPEG();
-         std::cerr << "Writting as JPEG" << std::endl;
          break;
    }
          break;
    }
-   CheckMandatoryElements();
-
    // --------------------------------------------------------------
    // Special Patch to allow gdcm to re-write ACR-LibIDO formated images
    //
    // --------------------------------------------------------------
    // Special Patch to allow gdcm to re-write ACR-LibIDO formated images
    //
@@ -725,9 +766,10 @@ bool FileHelper::Write(std::string const &fileName)
       check = FileInternal->Write(fileName,WriteType);
    }
 
       check = FileInternal->Write(fileName,WriteType);
    }
 
-   RestoreWrite();
-   RestoreWriteFileType();
-   RestoreWriteMandatory();
+   RestoreWrite(); 
+  // RestoreWriteFileType();
+  // RestoreWriteMandatory();
+   
 
    // --------------------------------------------------------------
    // Special Patch to allow gdcm to re-write ACR-LibIDO formated images
 
    // --------------------------------------------------------------
    // Special Patch to allow gdcm to re-write ACR-LibIDO formated images
@@ -766,6 +808,7 @@ bool FileHelper::CheckWriteIntegrity()
       size_t decSize = FileInternal->GetXSize()
                      * FileInternal->GetYSize() 
                      * FileInternal->GetZSize()
       size_t decSize = FileInternal->GetXSize()
                      * FileInternal->GetYSize() 
                      * FileInternal->GetZSize()
+                     * FileInternal->GetTSize()     
                      * FileInternal->GetSamplesPerPixel()
                      * ( numberBitsAllocated / 8 );
       size_t rgbSize = decSize;
                      * FileInternal->GetSamplesPerPixel()
                      * ( numberBitsAllocated / 8 );
       size_t rgbSize = decSize;
@@ -812,7 +855,7 @@ void FileHelper::SetWriteToRaw()
    } 
    else
    {
    } 
    else
    {
-      DataEntry *photInt = CopyDataEntry(0x0028,0x0004);
+      DataEntry *photInt = CopyDataEntry(0x0028,0x0004,"CS");
       if (FileInternal->HasLUT() )
       {
          photInt->SetString("PALETTE COLOR ");
       if (FileInternal->HasLUT() )
       {
          photInt->SetString("PALETTE COLOR ");
@@ -857,13 +900,13 @@ void FileHelper::SetWriteToRGB()
    {
       PixelReadConverter->BuildRGBImage();
       
    {
       PixelReadConverter->BuildRGBImage();
       
-      DataEntry *spp = CopyDataEntry(0x0028,0x0002);
+      DataEntry *spp = CopyDataEntry(0x0028,0x0002,"US");
       spp->SetString("3 ");
 
       spp->SetString("3 ");
 
-      DataEntry *planConfig = CopyDataEntry(0x0028,0x0006);
+      DataEntry *planConfig = CopyDataEntry(0x0028,0x0006,"US");
       planConfig->SetString("0 ");
 
       planConfig->SetString("0 ");
 
-      DataEntry *photInt = CopyDataEntry(0x0028,0x0004);
+      DataEntry *photInt = CopyDataEntry(0x0028,0x0004,"CS");
       photInt->SetString("RGB ");
 
       if ( PixelReadConverter->GetRGB() )
       photInt->SetString("RGB ");
 
       if ( PixelReadConverter->GetRGB() )
@@ -914,13 +957,13 @@ void FileHelper::SetWriteToRGB()
       // samples per pixels = 1 (in the read file)
       if ( FileInternal->GetBitsAllocated()==24 ) 
       {
       // samples per pixels = 1 (in the read file)
       if ( FileInternal->GetBitsAllocated()==24 ) 
       {
-         DataEntry *bitsAlloc = CopyDataEntry(0x0028,0x0100);
+         DataEntry *bitsAlloc = CopyDataEntry(0x0028,0x0100,"US");
          bitsAlloc->SetString("8 ");
 
          bitsAlloc->SetString("8 ");
 
-         DataEntry *bitsStored = CopyDataEntry(0x0028,0x0101);
+         DataEntry *bitsStored = CopyDataEntry(0x0028,0x0101,"US");
          bitsStored->SetString("8 ");
 
          bitsStored->SetString("8 ");
 
-         DataEntry *highBit = CopyDataEntry(0x0028,0x0102);
+         DataEntry *highBit = CopyDataEntry(0x0028,0x0102,"US");
          highBit->SetString("7 ");
 
          Archive->Push(bitsAlloc);
          highBit->SetString("7 ");
 
          Archive->Push(bitsAlloc);
@@ -943,8 +986,10 @@ void FileHelper::SetWriteToRGB()
  */ 
 void FileHelper::RestoreWrite()
 {
  */ 
 void FileHelper::RestoreWrite()
 {
+
    Archive->Restore(0x0028,0x0002);
    Archive->Restore(0x0028,0x0004);
    Archive->Restore(0x0028,0x0002);
    Archive->Restore(0x0028,0x0004);
+   
    Archive->Restore(0x0028,0x0006);
    Archive->Restore(GetFile()->GetGrPixel(),GetFile()->GetNumPixel());
 
    Archive->Restore(0x0028,0x0006);
    Archive->Restore(GetFile()->GetGrPixel(),GetFile()->GetNumPixel());
 
@@ -964,7 +1009,6 @@ void FileHelper::RestoreWrite()
    // For the Palette Color Lookup Table UID
    Archive->Restore(0x0028,0x1203); 
 
    // For the Palette Color Lookup Table UID
    Archive->Restore(0x0028,0x1203); 
 
-
    // group 0002 may be pushed out for ACR-NEMA writting purposes 
    Archive->Restore(0x0002,0x0000);
    Archive->Restore(0x0002,0x0001);
    // group 0002 may be pushed out for ACR-NEMA writting purposes 
    Archive->Restore(0x0002,0x0000);
    Archive->Restore(0x0002,0x0001);
@@ -976,6 +1020,7 @@ void FileHelper::RestoreWrite()
    Archive->Restore(0x0002,0x0016);
    Archive->Restore(0x0002,0x0100);
    Archive->Restore(0x0002,0x0102);
    Archive->Restore(0x0002,0x0016);
    Archive->Restore(0x0002,0x0100);
    Archive->Restore(0x0002,0x0102);
+
 }
 
 /**
 }
 
 /**
@@ -1000,28 +1045,30 @@ void FileHelper::SetWriteFileTypeToACR()
 }
 
 /**
 }
 
 /**
- * \brief Sets in the File the TransferSyntax to 'Explicit VR Little Endian"   
+ * \brief Sets in the File the TransferSyntax to 'JPEG'
  */ 
 void FileHelper::SetWriteFileTypeToJPEG()
 {
    std::string ts = Util::DicomString( 
       Global::GetTS()->GetSpecialTransferSyntax(TS::JPEGBaselineProcess1) );
 
  */ 
 void FileHelper::SetWriteFileTypeToJPEG()
 {
    std::string ts = Util::DicomString( 
       Global::GetTS()->GetSpecialTransferSyntax(TS::JPEGBaselineProcess1) );
 
-   DataEntry *tss = CopyDataEntry(0x0002,0x0010);
+   DataEntry *tss = CopyDataEntry(0x0002,0x0010,"UI");
    tss->SetString(ts);
 
    Archive->Push(tss);
    tss->Delete();
 }
 
    tss->SetString(ts);
 
    Archive->Push(tss);
    tss->Delete();
 }
 
+/**
+ * \brief Sets in the File the TransferSyntax to 'Explicit VR Little Endian"   
+ */ 
 void FileHelper::SetWriteFileTypeToExplicitVR()
 {
    std::string ts = Util::DicomString( 
       Global::GetTS()->GetSpecialTransferSyntax(TS::ExplicitVRLittleEndian) );
 
 void FileHelper::SetWriteFileTypeToExplicitVR()
 {
    std::string ts = Util::DicomString( 
       Global::GetTS()->GetSpecialTransferSyntax(TS::ExplicitVRLittleEndian) );
 
-   DataEntry *tss = CopyDataEntry(0x0002,0x0010);
+   DataEntry *tss = CopyDataEntry(0x0002,0x0010,"UI");
    tss->SetString(ts);
    tss->SetString(ts);
-
    Archive->Push(tss);
    tss->Delete();
 }
    Archive->Push(tss);
    tss->Delete();
 }
@@ -1034,9 +1081,8 @@ void FileHelper::SetWriteFileTypeToImplicitVR()
    std::string ts = Util::DicomString(
       Global::GetTS()->GetSpecialTransferSyntax(TS::ImplicitVRLittleEndian) );
 
    std::string ts = Util::DicomString(
       Global::GetTS()->GetSpecialTransferSyntax(TS::ImplicitVRLittleEndian) );
 
-   DataEntry *tss = CopyDataEntry(0x0002,0x0010);
+   DataEntry *tss = CopyDataEntry(0x0002,0x0010,"UI");
    tss->SetString(ts);
    tss->SetString(ts);
-
    Archive->Push(tss);
    tss->Delete();
 }
    Archive->Push(tss);
    tss->Delete();
 }
@@ -1061,9 +1107,12 @@ void FileHelper::SetWriteToLibido()
    {
       std::string rows, columns; 
 
    {
       std::string rows, columns; 
 
-      DataEntry *newRow=DataEntry::New(oldRow->GetDictEntry());
-      DataEntry *newCol=DataEntry::New(oldCol->GetDictEntry());
-
+      //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");
+      
       newRow->Copy(oldCol);
       newCol->Copy(oldRow);
 
       newRow->Copy(oldCol);
       newCol->Copy(oldRow);
 
@@ -1077,7 +1126,7 @@ void FileHelper::SetWriteToLibido()
       newCol->Delete();
    }
 
       newCol->Delete();
    }
 
-   DataEntry *libidoCode = CopyDataEntry(0x0008,0x0010);
+   DataEntry *libidoCode = CopyDataEntry(0x0008,0x0010,"LO");
    libidoCode->SetString("ACRNEMA_LIBIDO_1.1");
    Archive->Push(libidoCode);
    libidoCode->Delete();
    libidoCode->SetString("ACRNEMA_LIBIDO_1.1");
    Archive->Push(libidoCode);
    libidoCode->Delete();
@@ -1093,7 +1142,7 @@ void FileHelper::SetWriteToNoLibido()
    {
       if ( recCode->GetString() == "ACRNEMA_LIBIDO_1.1" )
       {
    {
       if ( recCode->GetString() == "ACRNEMA_LIBIDO_1.1" )
       {
-         DataEntry *libidoCode = CopyDataEntry(0x0008,0x0010);
+         DataEntry *libidoCode = CopyDataEntry(0x0008,0x0010,"LO");
          libidoCode->SetString("");
          Archive->Push(libidoCode);
          libidoCode->Delete();
          libidoCode->SetString("");
          Archive->Push(libidoCode);
          libidoCode->Delete();
@@ -1122,11 +1171,10 @@ void FileHelper::RestoreWriteOfLibido()
  * @param   group   Group number of the Entry 
  * @param   elem  Element number of the Entry
  * @param   vr  Value Representation of the Entry
  * @param   group   Group number of the Entry 
  * @param   elem  Element number of the Entry
  * @param   vr  Value Representation of the Entry
- *          FIXME : what is it used for?
  * \return  pointer to the new Bin Entry (NULL when creation failed).
  */ 
 DataEntry *FileHelper::CopyDataEntry(uint16_t group, uint16_t elem,
  * \return  pointer to the new Bin Entry (NULL when creation failed).
  */ 
 DataEntry *FileHelper::CopyDataEntry(uint16_t group, uint16_t elem,
-                                   const TagName &vr)
+                                   const VRKey &vr)
 {
    DocEntry *oldE = FileInternal->GetDocEntry(group, elem);
    DataEntry *newE;
 {
    DocEntry *oldE = FileInternal->GetDocEntry(group, elem);
    DataEntry *newE;
@@ -1137,7 +1185,8 @@ DataEntry *FileHelper::CopyDataEntry(uint16_t group, uint16_t elem,
 
    if ( oldE )
    {
 
    if ( oldE )
    {
-      newE = DataEntry::New(oldE->GetDictEntry());
+      //newE = DataEntry::New(oldE->GetDictEntry());
+      newE = DataEntry::New(group, elem, vr);
       newE->Copy(oldE);
    }
    else
       newE->Copy(oldE);
    }
    else
@@ -1188,11 +1237,16 @@ DataEntry *FileHelper::CopyDataEntry(uint16_t group, uint16_t elem,
 To be moved to User's guide / WIKI  ?
 
 We have to deal with 4 *very* different cases :
 To be moved to User's guide / WIKI  ?
 
 We have to deal with 4 *very* different cases :
--1) user created ex nihilo his own image  and wants to write it as a Dicom image.
+-1) user created ex nihilo his own image and wants to write it as a Dicom image.
+    USER_OWN_IMAGE
 -2) user modified the pixels of an existing image.
 -2) user modified the pixels of an existing image.
--3) user created a new image, using existing images (eg MIP, MPR, cartography image)
--4) user anonymized an image without processing the pixels.
-
+   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..
+   UNMODIFIED_PIXELS_IMAGE
+-Probabely some more to be added  
 gdcm::FileHelper::CheckMandatoryElements() deals automatically with these cases.
 
 1)2)3)4)
 gdcm::FileHelper::CheckMandatoryElements() deals automatically with these cases.
 
 1)2)3)4)
@@ -1209,17 +1263,15 @@ them.
      keeping the same 'Serie Instance UID' / 'Study Instance UID' for various images
  Warning :     
  The user shouldn't add any image to a 'Manufacturer Serie'
      keeping the same 'Serie Instance UID' / 'Study Instance UID' for various images
  Warning :     
  The user shouldn't add any image to a 'Manufacturer Serie'
-     but there is no way no to allowed him to do that
+     but there is no way no to allow him to do that
      
  None of the 'shadow elements' are droped out.
      
 
 1)
      
  None of the 'shadow elements' are droped out.
      
 
 1)
-'Modality' (0x0008,0x0060)       is defaulted to "OT" (other) if missing.
 'Conversion Type (0x0008,0x0064) is forced to 'SYN' (Synthetic Image).
 'Conversion Type (0x0008,0x0064) is forced to 'SYN' (Synthetic Image).
-'Study Date', 'Study Time' are defaulted to current Date and Time.
  
  
-1)2)3)
+1)3)
 'Media Storage SOP Class UID' (0x0002,0x0002)
 'SOP Class UID'               (0x0008,0x0016) are set to 
                                                [Secondary Capture Image Storage]
 'Media Storage SOP Class UID' (0x0002,0x0002)
 'SOP Class UID'               (0x0008,0x0016) are set to 
                                                [Secondary Capture Image Storage]
@@ -1242,14 +1294,11 @@ If 'SOP Class UID' exists in the native image  ('true DICOM' image)
           0008 1115 SQ 1 Referenced Series Sequence
           0008 1140 SQ 1 Referenced Image Sequence
        
           0008 1115 SQ 1 Referenced Series Sequence
           0008 1140 SQ 1 Referenced Image Sequence
        
-4) When user *knows* he didn't modified the pixels, he may ask the writer to keep some
-informations unchanged :
+4) When user *knows* he didn't modified the pixels, we keep some informations unchanged :
 'Media Storage SOP Class UID' (0x0002,0x0002)
 'SOP Class UID'               (0x0008,0x0016)
 'Image Type'                  (0x0008,0x0008)
 'Conversion Type'             (0x0008,0x0064)
 'Media Storage SOP Class UID' (0x0002,0x0002)
 'SOP Class UID'               (0x0008,0x0016)
 'Image Type'                  (0x0008,0x0008)
 'Conversion Type'             (0x0008,0x0064)
-He has to use gdcm::FileHelper::SetKeepMediaStorageSOPClassUID(true)
-(probabely name has to be changed)
 
 
 Bellow follows the full description (hope so !) of the consistency checks performed 
 
 
 Bellow follows the full description (hope so !) of the consistency checks performed 
@@ -1257,23 +1306,16 @@ by gdcm::FileHelper::CheckMandatoryElements()
 
 
 -->'Media Storage SOP Class UID' (0x0002,0x0002)
 
 
 -->'Media Storage SOP Class UID' (0x0002,0x0002)
--->'SOP Class UID'               (0x0008,0x0016) are set to 
+-->'SOP Class UID'               (0x0008,0x0016) are defaulted to 
                                                [Secondary Capture Image Storage]
                                                [Secondary Capture Image Storage]
-   (Potentialy, the image was modified by user, and post-processed; 
-    it's no longer a 'native' image)
-  Except if user told he wants to keep MediaStorageSOPClassUID,
-  when *he* knows he didn't modify the image (e.g. : he just anonymized the file)
-
 --> 'Image Type'  (0x0008,0x0008)
      is forced to  "DERIVED\PRIMARY"
      (The written image is no longer an 'ORIGINAL' one)
 --> 'Image Type'  (0x0008,0x0008)
      is forced to  "DERIVED\PRIMARY"
      (The written image is no longer an 'ORIGINAL' one)
-  Except if user told he wants to keep MediaStorageSOPClassUID,
-  when *he* knows he didn't modify the image (e.g. : he just anonymized the file)
+  Except if user knows he didn't modify the image (e.g. : he just anonymized the file)
    
  -->  Conversion Type (0x0008,0x0064)
    
  -->  Conversion Type (0x0008,0x0064)
-     is forced to 'SYN' (Synthetic Image)
-  Except if user told he wants to keep MediaStorageSOPClassUID,
-  when *he* knows he didn't modify the image (e.g. : he just anonymized the file)
+     is defaulted to 'SYN' (Synthetic Image)
+  when *he* knows he created his own image ex nihilo
             
 --> 'Modality' (0x0008,0x0060)   
     is defaulted to "OT" (other) if missing.   
             
 --> 'Modality' (0x0008,0x0060)   
     is defaulted to "OT" (other) if missing.   
@@ -1324,14 +1366,15 @@ by gdcm::FileHelper::CheckMandatoryElements()
     
 --> Patient ID, Patient's Birth Date, Patient's Sex, (Type 2)
 --> Referring Physician's Name  (Type 2)
     
 --> Patient ID, Patient's Birth Date, Patient's Sex, (Type 2)
 --> Referring Physician's Name  (Type 2)
-    are created, with empty value if there are missing.  
+    are created, with empty value if there are missing.
 
  -------------------------------------------------------------------------------------*/
 
  -------------------------------------------------------------------------------------*/
+
 void FileHelper::CheckMandatoryElements()
 {
    std::string sop =  Util::CreateUniqueUID();
 void FileHelper::CheckMandatoryElements()
 {
    std::string sop =  Util::CreateUniqueUID();
-   
+
+   // --------------------- For Meta Elements ---------------------
    // just to remember : 'official' 0002 group
    if ( WriteType != ACR && WriteType != ACR_LIBIDO )
    {
    // just to remember : 'official' 0002 group
    if ( WriteType != ACR && WriteType != ACR_LIBIDO )
    {
@@ -1351,8 +1394,8 @@ void FileHelper::CheckMandatoryElements()
    // Create them if not found
    // Always modify the value
    // Push the entries to the archive.
    // Create them if not found
    // Always modify the value
    // Push the entries to the archive.
-      CopyMandatoryEntry(0x0002,0x0000,"0");
+      CopyMandatoryEntry(0x0002,0x0000,"0","UL");
+
       DataEntry *e_0002_0001 = CopyDataEntry(0x0002,0x0001, "OB");
       e_0002_0001->SetBinArea((uint8_t*)Util::GetFileMetaInformationVersion(),
                                false);
       DataEntry *e_0002_0001 = CopyDataEntry(0x0002,0x0001, "OB");
       e_0002_0001->SetBinArea((uint8_t*)Util::GetFileMetaInformationVersion(),
                                false);
@@ -1360,40 +1403,119 @@ void FileHelper::CheckMandatoryElements()
       Archive->Push(e_0002_0001);
       e_0002_0001->Delete(); 
 
       Archive->Push(e_0002_0001);
       e_0002_0001->Delete(); 
 
-      if ( KeepMediaStorageSOPClassUID)      
-   // It up to the use to *know* whether he modified the pixels or not.
-   // he is allowed to keep the original 'Media Storage SOP Class UID'
-         CheckMandatoryEntry(0x0002,0x0002,"1.2.840.10008.5.1.4.1.1.7");    
+      if ( ContentType == FILTERED_IMAGE || ContentType == UNMODIFIED_PIXELS_IMAGE)
+      {      
+   // we keep the original 'Media Storage SOP Class UID', we default it if missing
+         CheckMandatoryEntry(0x0002,0x0002,"1.2.840.10008.5.1.4.1.1.7","UI"); 
+      }
       else
       else
-   // Potentialy this is a post-processed image 
+      {
+   // It's *not* an image comming straight from a source. We force
    // 'Media Storage SOP Class UID'  --> [Secondary Capture Image Storage]
    // 'Media Storage SOP Class UID'  --> [Secondary Capture Image Storage]
-         CopyMandatoryEntry(0x0002,0x0002,"1.2.840.10008.5.1.4.1.1.7");    
-       
+         CopyMandatoryEntry(0x0002,0x0002,"1.2.840.10008.5.1.4.1.1.7","UI");
+      }
+      
    // 'Media Storage SOP Instance UID'   
    // 'Media Storage SOP Instance UID'   
-      CopyMandatoryEntry(0x0002,0x0003,sop);
+      CopyMandatoryEntry(0x0002,0x0003,sop,"UI");
       
    // 'Implementation Class UID'
    // FIXME : in all examples we have, 0x0002,0x0012 is not so long :
       
    // 'Implementation Class UID'
    // FIXME : in all examples we have, 0x0002,0x0012 is not so long :
-   //         semms to be Root UID + 4 digits (?)
-      CopyMandatoryEntry(0x0002,0x0012,Util::CreateUniqueUID());
+   //         seems to be Root UID + 4 digits (?)
+      CopyMandatoryEntry(0x0002,0x0012,Util::CreateUniqueUID(),"UI");
 
    // 'Implementation Version Name'
       std::string version = "GDCM ";
       version += Util::GetVersion();
 
    // 'Implementation Version Name'
       std::string version = "GDCM ";
       version += Util::GetVersion();
-      CopyMandatoryEntry(0x0002,0x0013,version);
+      CopyMandatoryEntry(0x0002,0x0013,version,"SH");
    }
 
    }
 
+   // --------------------- For DataSet ---------------------
+
+   if ( ContentType != USER_OWN_IMAGE) // when it's not a user made image
+   { 
+   
+      gdcmDebugMacro( "USER_OWN_IMAGE (1)");
+    // If 'SOP Class UID' exists ('true DICOM' image)
+   // we create the 'Source Image Sequence' SeqEntry
+   // to hold informations about the Source Image
+  
+      DataEntry *e_0008_0016 = FileInternal->GetDataEntry(0x0008, 0x0016);
+      if ( e_0008_0016 )
+      {
+      // Create 'Source Image Sequence' SeqEntry
+//     SeqEntry *sis = SeqEntry::New (
+//            Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x2112) );
+      SeqEntry *sis = SeqEntry::New (0x0008, 0x2112);
+      SQItem *sqi = SQItem::New(1);
+      // (we assume 'SOP Instance UID' exists too) 
+      // create 'Referenced SOP Class UID'
+//     DataEntry *e_0008_1150 = DataEntry::New(
+//            Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x1150) );
+      DataEntry *e_0008_1150 = DataEntry::New(0x0008, 0x1150, "UI");
+      e_0008_1150->SetString( e_0008_0016->GetString());
+      sqi->AddEntry(e_0008_1150);
+      e_0008_1150->Delete();
+      
+      // create 'Referenced SOP Instance UID'
+      DataEntry *e_0008_0018 = FileInternal->GetDataEntry(0x0008, 0x0018);
+//      DataEntry *e_0008_1155 = DataEntry::New(
+//            Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x1155) );
+      DataEntry *e_0008_1155 = DataEntry::New(0x0008, 0x1155, "UI");
+      e_0008_1155->SetString( e_0008_0018->GetString());
+      sqi->AddEntry(e_0008_1155);
+      e_0008_1155->Delete();
+
+      sis->AddSQItem(sqi,1);
+      sqi->Delete();
+
+      // temporarily replaces any previous 'Source Image Sequence' 
+      Archive->Push(sis);
+      sis->Delete();
+      // FIXME : is 'Image Type' *really* depending on the presence of 'SOP Class UID'?
+       if ( ContentType == FILTERED_IMAGE)      
+      // the user *knows* he just modified the pixels
+      // the image is no longer an 'Original' one
+         CopyMandatoryEntry(0x0008,0x0008,"DERIVED\\PRIMARY","CS");    
+      }
+   }
+      
+   if ( ContentType == FILTERED_IMAGE || ContentType == UNMODIFIED_PIXELS_IMAGE)
+   {      
+   // we keep the original 'Media Storage SOP Class UID', we default it if missing (it should be present !)
+         CheckMandatoryEntry(0x0008,0x0016,"1.2.840.10008.5.1.4.1.1.7","UI");      
+   }
+   else
+   {
+   // It's *not* an image comming straight from a source. We force
+   // 'Media Storage SOP Class UID'  --> [Secondary Capture Image Storage]
+         CopyMandatoryEntry(0x0008,0x0016,"1.2.840.10008.5.1.4.1.1.7", "UI");      
+   }
+     
+   Archive->Push(0x0028,0x005); // [Image Dimensions (RET)
    // Push out 'LibIDO-special' entries, if any
    Archive->Push(0x0028,0x0015);
    Archive->Push(0x0028,0x0016);
    Archive->Push(0x0028,0x0017);
    // Push out 'LibIDO-special' entries, if any
    Archive->Push(0x0028,0x0015);
    Archive->Push(0x0028,0x0016);
    Archive->Push(0x0028,0x0017);
-   Archive->Push(0x0028,0x00199);
+   Archive->Push(0x0028,0x0198);  // very old versions
+   Archive->Push(0x0028,0x0199);
+   // Replace deprecated 0028 0012 US Planes   
+   // by new             0028 0008 IS Number of Frames
+   
+  ///\todo : find if there is a rule!
+   DataEntry *e_0028_0012 = FileInternal->GetDataEntry(0x0028, 0x0012);
+   if ( e_0028_0012 )
+   {
+      CopyMandatoryEntry(0x0028, 0x0008,e_0028_0012->GetString(),"IS");
+      Archive->Push(0x0028,0x0012);      
+   }
 
    // Deal with the pb of (Bits Stored = 12)
    // - we're gonna write the image as Bits Stored = 16
    if ( FileInternal->GetEntryString(0x0028,0x0100) ==  "12")
    {
 
    // Deal with the pb of (Bits Stored = 12)
    // - we're gonna write the image as Bits Stored = 16
    if ( FileInternal->GetEntryString(0x0028,0x0100) ==  "12")
    {
-      CopyMandatoryEntry(0x0028,0x0100,"16");
+      CopyMandatoryEntry(0x0028,0x0100,"16","US");
    }
 
    // Check if user wasn't drunk ;-)
    }
 
    // Check if user wasn't drunk ;-)
@@ -1403,7 +1525,7 @@ void FileHelper::CheckMandatoryElements()
    int nbBitsAllocated = FileInternal->GetBitsAllocated();
    if ( nbBitsAllocated == 0 || nbBitsAllocated > 32)
    {
    int nbBitsAllocated = FileInternal->GetBitsAllocated();
    if ( nbBitsAllocated == 0 || nbBitsAllocated > 32)
    {
-      CopyMandatoryEntry(0x0028,0x0100,"16");
+      CopyMandatoryEntry(0x0028,0x0100,"16","US");
       gdcmWarningMacro("(0028,0100) changed from "
          << nbBitsAllocated << " to 16 for consistency purpose");
       nbBitsAllocated = 16; 
       gdcmWarningMacro("(0028,0100) changed from "
          << nbBitsAllocated << " to 16 for consistency purpose");
       nbBitsAllocated = 16; 
@@ -1414,7 +1536,7 @@ void FileHelper::CheckMandatoryElements()
    {
       s.str("");
       s << nbBitsAllocated;
    {
       s.str("");
       s << nbBitsAllocated;
-      CopyMandatoryEntry(0x0028,0x0101,s.str());
+      CopyMandatoryEntry(0x0028,0x0101,s.str(),"US");
       gdcmWarningMacro("(0028,0101) changed from "
                        << nbBitsStored << " to " << nbBitsAllocated
                        << " for consistency purpose" );
       gdcmWarningMacro("(0028,0101) changed from "
                        << nbBitsStored << " to " << nbBitsAllocated
                        << " for consistency purpose" );
@@ -1428,7 +1550,7 @@ void FileHelper::CheckMandatoryElements()
    {
       s.str("");
       s << nbBitsStored - 1; 
    {
       s.str("");
       s << nbBitsStored - 1; 
-      CopyMandatoryEntry(0x0028,0x0102,s.str());
+      CopyMandatoryEntry(0x0028,0x0102,s.str(),"US");
       gdcmWarningMacro("(0028,0102) changed from "
                        << highBitPosition << " to " << nbBitsAllocated-1
                        << " for consistency purpose");
       gdcmWarningMacro("(0028,0102) changed from "
                        << highBitPosition << " to " << nbBitsAllocated-1
                        << " for consistency purpose");
@@ -1439,95 +1561,78 @@ void FileHelper::CheckMandatoryElements()
    {
       pixelSpacing = "1.0\\1.0";
        // if missing, Pixel Spacing forced to "1.0\1.0"
    {
       pixelSpacing = "1.0\\1.0";
        // if missing, Pixel Spacing forced to "1.0\1.0"
-      CopyMandatoryEntry(0x0028,0x0030,pixelSpacing);
+      CopyMandatoryEntry(0x0028,0x0030,pixelSpacing,"DS");
    }
    
    // 'Imager Pixel Spacing' : defaulted to 'Pixel Spacing'
    // --> This one is the *legal* one !
    }
    
    // 'Imager Pixel Spacing' : defaulted to 'Pixel Spacing'
    // --> This one is the *legal* one !
-   // FIXME : we should write it only when we are *sure* the image comes from
+   if ( ContentType != USER_OWN_IMAGE)
+   //  we write it only when we are *sure* the image comes from
    //         an imager (see also 0008,0x0064)          
    //         an imager (see also 0008,0x0064)          
-   CheckMandatoryEntry(0x0018,0x1164,pixelSpacing);
-   
-   // Samples Per Pixel (type 1) : default to grayscale 
-   CheckMandatoryEntry(0x0028,0x0002,"1");
-   
-   // --- Check UID-related Entries ---
+      CheckMandatoryEntry(0x0018,0x1164,pixelSpacing,"DS");
 
 
-   // If 'SOP Class UID' exists ('true DICOM' image)
-   // we create the 'Source Image Sequence' SeqEntry
-   // to hold informations about the Source Image
 
 
-   DataEntry *e_0008_0016 = FileInternal->GetDataEntry(0x0008, 0x0016);
-   if ( e_0008_0016 )
-   {
-      // Create 'Source Image Sequence' SeqEntry
-      SeqEntry *sis = SeqEntry::New (
-            Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x2112) );
-      SQItem *sqi = SQItem::New(1);
-      // (we assume 'SOP Instance UID' exists too) 
-      // create 'Referenced SOP Class UID'
-      DataEntry *e_0008_1150 = DataEntry::New(
-            Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x1150) );
-      e_0008_1150->SetString( e_0008_0016->GetString());
-      sqi->AddEntry(e_0008_1150);
-      e_0008_1150->Delete();
-      
-      // create 'Referenced SOP Instance UID'
-      DataEntry *e_0008_0018 = FileInternal->GetDataEntry(0x0008, 0x0018);
-      DataEntry *e_0008_1155 = DataEntry::New(
-            Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x1155) );
-      e_0008_1155->SetString( e_0008_0018->GetString());
-      sqi->AddEntry(e_0008_1155);
-      e_0008_1155->Delete();
 
 
-      sis->AddSQItem(sqi,1);
-      sqi->Delete();
-
-      // temporarily replaces any previous 'Source Image Sequence' 
-      Archive->Push(sis);
-      sis->Delete();
+/*
+///Exact meaning of RETired fields
+
+// See page 73 of ACR-NEMA_300-1988.pdf !
+
+// 0020,0020 : Patient Orientation : 
+Patient direction of the first row and
+column of the images. The first entry id the direction of the raws, given by the
+direction of the last pixel in the first row from the first pixel in tha row.
+the second entry is the direction of the columns, given by the direction of the
+last pixel in the first column from the first pixel in that column.
+L : Left, F : Feet, A : Anterior, P : Posterior.
+Up to 3 letters can be used in combination to indicate oblique planes.
+
+//0020,0030 Image Position (RET)
+x,y,z coordinates im mm of the first pixel in the image
+
+// 0020,0035 Image Orientation (RET)
+Direction cosines of the R axis of the image system with respect to the
+equipment coordinate axes x,y,z, followed by direction cosines of the C axis of
+the image system with respect to the same axes
+
+//0020,0050 Location
+An image location reference, standard for the modality (such as CT bed
+position), used to indicate position. Calculation of position for other purposes
+is only from (0020,0030) and (0020,0035)
+*/
  
  
-      // FIXME : is 'Image Type' *really* depending on the presence of'SOP Class UID'?
-       if ( KeepMediaStorageSOPClassUID)      
-   // It up to the use to *know* whether he modified the pixels or not.
-   // he is allowed to keep the original 'Media Storage SOP Class UID'
-   // and 'Image Type' as well
-         CheckMandatoryEntry(0x0008,0x0008,"DERIVED\\PRIMARY");    
-      else
-   // Potentialy this is a post-processed image 
-   // (The written image is no longer an 'ORIGINAL' one)
-      CopyMandatoryEntry(0x0008,0x0008,"DERIVED\\PRIMARY");
+/*
+// if imagePositionPatient    not found, default it with imagePositionRet,    if any
+// if imageOrientationPatient not found, default it with imageOrientationRet, if any
 
 
-   }
+   std::string imagePositionRet        = FileInternal->GetEntryString(0x0020,0x0030);
+   std::string imageOrientationRet     = FileInternal->GetEntryString(0x0020,0x0035);
+   std::string imagePositionPatient    = FileInternal->GetEntryString(0x0020,0x0032);
+   std::string imageOrientationPatient = FileInternal->GetEntryString(0x0020,0x0037);
+   
+   if(  imagePositionPatient == GDCM_UNFOUND && imageOrientationPatient == GDCM_UNFOUND
+     && imagePositionRet     != GDCM_UNFOUND && imageOrientationRet     != GDCM_UNFOUND)
+   {
+      CopyMandatoryEntry(0x0020, 0x0032,imagePositionRet,"DS");
+      Archive->Push(0x0020,0x0030); 
+      CopyMandatoryEntry(0x0020, 0x0037,imageOrientationRet,"DS");
+      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'   
    // 'SOP Instance UID'  
    // At the end, not to overwrite the original ones,
    // needed by 'Referenced SOP Instance UID', 'Referenced SOP Class UID'   
    // 'SOP Instance UID'  
-   CopyMandatoryEntry(0x0008,0x0018,sop);
-   
-   // the gdcm written image is a [Secondary Capture Image Storage]
-   // except if user told us he dind't modify the pixels, and, therefore
-   // he want to keep the 'Media Storage SOP Class UID'
-   
-      // 'Media Storage SOP Class UID' : [Secondary Capture Image Storage]
-   if ( KeepMediaStorageSOPClassUID)
-   {      
-      // It up to the use to *know* whether he modified the pixels or not.
-      // he is allowed to keep the original 'Media Storage SOP Class UID'
-      CheckMandatoryEntry(0x0008,0x0016,"1.2.840.10008.5.1.4.1.1.7");    
-   }
-   else
-   {
-       // Potentialy this is a post-processed image 
-       // 'Media Storage SOP Class UID'  --> [Secondary Capture Image Storage]
-      CopyMandatoryEntry(0x0008,0x0016,"1.2.840.10008.5.1.4.1.1.7");    
-
-       // FIXME : Must we Force Value, or Default value ?
-       // Is it Type 1 for any Modality ?
-       //    --> Answer seems to be NO :-(
-       // FIXME : we should write it only when we are *sure* the image 
-       //         *does not* come from an imager (see also 0018,0x1164)
+   CopyMandatoryEntry(0x0008,0x0018,sop,"UI");
 
 
+   if ( ContentType == USER_OWN_IMAGE)
+   {
+      gdcmDebugMacro( "USER_OWN_IMAGE (2)");   
        // Conversion Type.
        // Other possible values are :
        // See PS 3.3, Page 408
        // Conversion Type.
        // Other possible values are :
        // See PS 3.3, Page 408
@@ -1540,31 +1645,38 @@ void FileHelper::CheckMandatoryElements()
        // SI = Scanned Image
        // DRW = Drawing
        // SYN = Synthetic Image
        // SI = Scanned Image
        // DRW = Drawing
        // SYN = Synthetic Image
-     
-      CheckMandatoryEntry(0x0008,0x0064,"SYN");
-   }   
            
            
-   // ---- The user will never have to take any action on the following ----
+      CheckMandatoryEntry(0x0008,0x0064,"SYN","CS"); // Why not?
+   } 
+/*
+   if ( ContentType == CREATED_IMAGE)
+   {
+   /// \todo : find a trick to pass the Media Storage SOP Instance UID of the images used to create the current image
    
    
+   }
+*/
+           
+   // ---- The user will never have to take any action on the following ----
+
    // new value for 'SOP Instance UID'
    //SetMandatoryEntry(0x0008,0x0018,Util::CreateUniqueUID());
 
    // Instance Creation Date
    const std::string &date = Util::GetCurrentDate();
    // new value for 'SOP Instance UID'
    //SetMandatoryEntry(0x0008,0x0018,Util::CreateUniqueUID());
 
    // Instance Creation Date
    const std::string &date = Util::GetCurrentDate();
-   CopyMandatoryEntry(0x0008,0x0012,date);
+   CopyMandatoryEntry(0x0008,0x0012,date,"DA");
  
    // Instance Creation Time
    const std::string &time = Util::GetCurrentTime();
  
    // Instance Creation Time
    const std::string &time = Util::GetCurrentTime();
-   CopyMandatoryEntry(0x0008,0x0013,time);
+   CopyMandatoryEntry(0x0008,0x0013,time,"TM");
 
    // Study Date
 
    // Study Date
-   CheckMandatoryEntry(0x0008,0x0020,date);
+   CheckMandatoryEntry(0x0008,0x0020,date,"DA");
    // Study Time
    // Study Time
-   CheckMandatoryEntry(0x0008,0x0030,time);
+   CheckMandatoryEntry(0x0008,0x0030,time,"TM");
 
    // Accession Number
    //CopyMandatoryEntry(0x0008,0x0050,"");
 
    // Accession Number
    //CopyMandatoryEntry(0x0008,0x0050,"");
-   CheckMandatoryEntry(0x0008,0x0050,"");
+   CheckMandatoryEntry(0x0008,0x0050,"","SH");
    
 
    // ----- Add Mandatory Entries if missing ---
    
 
    // ----- Add Mandatory Entries if missing ---
@@ -1582,7 +1694,7 @@ void FileHelper::CheckMandatoryElements()
    //          keeping the same 'Study Instance UID' for various images
    // The user may add images to a 'Manufacturer Study',
    //          adding new Series to an already existing Study 
    //          keeping the same 'Study Instance UID' for various images
    // The user may add images to a 'Manufacturer Study',
    //          adding new Series to an already existing Study 
-   CheckMandatoryEntry(0x0020,0x000d,Util::CreateUniqueUID());
+   CheckMandatoryEntry(0x0020,0x000d,Util::CreateUniqueUID(),"UI");
 
    // 'Serie Instance UID'
    // Keep the value if exists
 
    // 'Serie Instance UID'
    // Keep the value if exists
@@ -1590,65 +1702,58 @@ void FileHelper::CheckMandatoryElements()
    // keeping the same 'Serie Instance UID' for various images
    // The user shouldn't add any image to a 'Manufacturer Serie'
    // but there is no way no to prevent him for doing that 
    // keeping the same 'Serie Instance UID' for various images
    // The user shouldn't add any image to a 'Manufacturer Serie'
    // but there is no way no to prevent him for doing that 
-   CheckMandatoryEntry(0x0020,0x000e,Util::CreateUniqueUID());
+   CheckMandatoryEntry(0x0020,0x000e,Util::CreateUniqueUID(),"UI");
 
    // Study ID
 
    // Study ID
-   CheckMandatoryEntry(0x0020,0x0010,"");
+   CheckMandatoryEntry(0x0020,0x0010,"","SH");
 
    // Series Number
 
    // Series Number
-   CheckMandatoryEntry(0x0020,0x0011,"");
+   CheckMandatoryEntry(0x0020,0x0011,"","IS");
 
    // Instance Number
 
    // Instance Number
-   CheckMandatoryEntry(0x0020,0x0013,"");
+   CheckMandatoryEntry(0x0020,0x0013,"","IS");
    
    // Patient Orientation
    // Can be computed from (0020|0037) :  Image Orientation (Patient)
    gdcm::Orientation *o = gdcm::Orientation::New();
    std::string ori = o->GetOrientation ( FileInternal );
    o->Delete();
    
    // Patient Orientation
    // Can be computed from (0020|0037) :  Image Orientation (Patient)
    gdcm::Orientation *o = gdcm::Orientation::New();
    std::string ori = o->GetOrientation ( FileInternal );
    o->Delete();
-   if (ori != "\\" )
-      CheckMandatoryEntry(0x0020,0x0020,ori);
+   if (ori != "\\" && ori != GDCM_UNFOUND)
+      CheckMandatoryEntry(0x0020,0x0020,ori,"CS");
    else   
    else   
-      CheckMandatoryEntry(0x0020,0x0020,"");
-   
+      CheckMandatoryEntry(0x0020,0x0020,"","CS");
+
+   // Default Patient Position to HFS
+   CheckMandatoryEntry(0x0018,0x5100,"HFS","CS");
+
    // Modality : if missing we set it to 'OTher'
    // Modality : if missing we set it to 'OTher'
-   CheckMandatoryEntry(0x0008,0x0060,"OT");
+   CheckMandatoryEntry(0x0008,0x0060,"OT","CS");
 
    // Manufacturer : if missing we set it to 'GDCM Factory'
 
    // Manufacturer : if missing we set it to 'GDCM Factory'
-   CheckMandatoryEntry(0x0008,0x0070,"GDCM Factory");
+   CheckMandatoryEntry(0x0008,0x0070,"GDCM Factory","LO");
 
    // Institution Name : if missing we set it to 'GDCM Hospital'
 
    // Institution Name : if missing we set it to 'GDCM Hospital'
-   CheckMandatoryEntry(0x0008,0x0080,"GDCM Hospital");
+   CheckMandatoryEntry(0x0008,0x0080,"GDCM Hospital","LO");
 
    // Patient's Name : if missing, we set it to 'GDCM^Patient'
 
    // Patient's Name : if missing, we set it to 'GDCM^Patient'
-   CheckMandatoryEntry(0x0010,0x0010,"GDCM^Patient");
+   CheckMandatoryEntry(0x0010,0x0010,"GDCM^Patient","PN");
 
 
-   // Patient ID
-   CheckMandatoryEntry(0x0010,0x0020,"");
+   // Patient ID : some clinical softwares *demand* it although it's a 'type 2' entry.
+   CheckMandatoryEntry(0x0010,0x0020,"gdcm ID","LO");
 
    // Patient's Birth Date : 'type 2' entry -> must exist, value not mandatory
 
    // Patient's Birth Date : 'type 2' entry -> must exist, value not mandatory
-   CheckMandatoryEntry(0x0010,0x0030,"");
+   CheckMandatoryEntry(0x0010,0x0030,"","DA");
 
    // Patient's Sex :'type 2' entry -> must exist, value not mandatory
 
    // Patient's Sex :'type 2' entry -> must exist, value not mandatory
-   CheckMandatoryEntry(0x0010,0x0040,"");
+   CheckMandatoryEntry(0x0010,0x0040,"","CS");
 
    // Referring Physician's Name :'type 2' entry -> must exist, value not mandatory
 
    // Referring Physician's Name :'type 2' entry -> must exist, value not mandatory
-   CheckMandatoryEntry(0x0008,0x0090,"");
-   
-   // Remove some inconstencies (probably some more will be added)
+   CheckMandatoryEntry(0x0008,0x0090,"","PN");
 
 
-   // if (0028 0008)Number of Frames exists
-   //    Push out (0020 0052),Frame of Reference UID
-   //    (only meaningfull within a Serie)
-   DataEntry *e_0028_0008 = FileInternal->GetDataEntry(0x0028, 0x0008);
-   if ( !e_0028_0008 )
-   {
-      Archive->Push(0x0020, 0x0052);
-   }
+ /*
    // Deal with element 0x0000 (group length) of each group.
    // First stage : get all the different Groups
    // Deal with element 0x0000 (group length) of each group.
    // First stage : get all the different Groups
- /*
+   
   GroupHT grHT;
   DocEntry *d = FileInternal->GetFirstEntry();
   while(d)
   GroupHT grHT;
   DocEntry *d = FileInternal->GetFirstEntry();
   while(d)
@@ -1662,32 +1767,36 @@ void FileHelper::CheckMandatoryElements()
       CheckMandatoryEntry(it->first, 0x0000, "0"); 
   }    
   // Third stage : update all 'zero level' groups length
       CheckMandatoryEntry(it->first, 0x0000, "0"); 
   }    
   // Third stage : update all 'zero level' groups length
-*/   
+*/ 
+
 } 
 
 } 
 
-void FileHelper::CheckMandatoryEntry(uint16_t group,uint16_t elem,std::string value)
+void FileHelper::CheckMandatoryEntry(uint16_t group,uint16_t elem,std::string value,const VRKey &vr )
 {
    DataEntry *entry = FileInternal->GetDataEntry(group,elem);
    if ( !entry )
    {
 {
    DataEntry *entry = FileInternal->GetDataEntry(group,elem);
    if ( !entry )
    {
-      entry = DataEntry::New(Global::GetDicts()->GetDefaultPubDict()->GetEntry(group,elem));
+      //entry = DataEntry::New(Global::GetDicts()->GetDefaultPubDict()->GetEntry(group,elem));
+      entry = DataEntry::New(group,elem,vr);
       entry->SetString(value);
       Archive->Push(entry);
       entry->Delete();
       entry->SetString(value);
       Archive->Push(entry);
       entry->Delete();
-   }
+   }    
 }
 
 }
 
-void FileHelper::SetMandatoryEntry(uint16_t group,uint16_t elem,std::string value)
+/// \todo : what is it used for ? (FileHelper::SetMandatoryEntry) 
+void FileHelper::SetMandatoryEntry(uint16_t group,uint16_t elem,std::string value,const VRKey &vr)
 {
 {
-   DataEntry *entry = DataEntry::New(Global::GetDicts()->GetDefaultPubDict()->GetEntry(group,elem));
+   //DataEntry *entry = DataEntry::New(Global::GetDicts()->GetDefaultPubDict()->GetEntry(group,elem));
+   DataEntry *entry = DataEntry::New(group,elem,vr);
    entry->SetString(value);
    Archive->Push(entry);
    entry->Delete();
 }
 
    entry->SetString(value);
    Archive->Push(entry);
    entry->Delete();
 }
 
-void FileHelper::CopyMandatoryEntry(uint16_t group,uint16_t elem,std::string value)
+void FileHelper::CopyMandatoryEntry(uint16_t group,uint16_t elem,std::string value,const VRKey &vr)
 {
 {
-   DataEntry *entry = CopyDataEntry(group,elem);
+   DataEntry *entry = CopyDataEntry(group,elem,vr);
    entry->SetString(value);
    Archive->Push(entry);
    entry->Delete();
    entry->SetString(value);
    Archive->Push(entry);
    entry->Delete();
@@ -1766,7 +1875,7 @@ void FileHelper::CallEndMethod()
 void FileHelper::Initialize()
 {
    UserFunction = 0;
 void FileHelper::Initialize()
 {
    UserFunction = 0;
-   KeepMediaStorageSOPClassUID = false;
+   ContentType = USER_OWN_IMAGE;
    
    WriteMode = WMODE_RAW;
    WriteType = ExplicitVR;
    
    WriteMode = WMODE_RAW;
    WriteType = ExplicitVR;