]> Creatis software - gdcm.git/blobdiff - src/gdcmFileHelper.cxx
Avoid warnings
[gdcm.git] / src / gdcmFileHelper.cxx
index 8bae1e02d661d26fd95595673ec49053944d8a5a..7e7be8e5a5b93d2823e73fb440c20e264f622466 100644 (file)
@@ -4,8 +4,8 @@
   Module:    $RCSfile: gdcmFileHelper.cxx,v $
   Language:  C++
 
   Module:    $RCSfile: gdcmFileHelper.cxx,v $
   Language:  C++
 
-  Date:      $Date: 2006/01/19 11:46:45 $
-  Version:   $Revision: 1.88 $
+  Date:      $Date: 2006/03/29 16:09:48 $
+  Version:   $Revision: 1.98 $
                                                                                 
   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 
 
 #include <fstream>
 
 
 #include <fstream>
 
@@ -69,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);)
@@ -233,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);
 }
@@ -249,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);
 }
@@ -281,7 +286,7 @@ 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)
 {
    return FileInternal->InsertEntryBinArea(binArea, lgth, group, elem);
 }
 {
    return FileInternal->InsertEntryBinArea(binArea, lgth, group, elem);
 }
@@ -377,7 +382,7 @@ 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 ()
 {
  */
 uint8_t *FileHelper::GetImageDataRaw ()
 {
@@ -386,7 +391,7 @@ uint8_t *FileHelper::GetImageDataRaw ()
 
 #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
@@ -394,7 +399,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 
@@ -403,12 +408,12 @@ 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.
  */
 size_t FileHelper::GetImageDataIntoVector (void *destination, size_t maxSize)
  *          failure e.g. MaxSize is lower than necessary.
  */
 size_t FileHelper::GetImageDataIntoVector (void *destination, size_t maxSize)
@@ -656,15 +661,44 @@ bool FileHelper::WriteAcr (std::string const &fileName)
  */
 bool FileHelper::Write(std::string const &fileName)
 {
  */
 bool FileHelper::Write(std::string const &fileName)
 {
+   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;
       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,11 +712,13 @@ bool FileHelper::Write(std::string const &fileName)
          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();
 
    // --------------------------------------------------------------
    CheckMandatoryElements();
 
    // --------------------------------------------------------------
@@ -762,6 +798,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;
@@ -996,7 +1033,7 @@ 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()
 {
  */ 
 void FileHelper::SetWriteFileTypeToJPEG()
 {
@@ -1010,6 +1047,9 @@ void FileHelper::SetWriteFileTypeToJPEG()
    tss->Delete();
 }
 
    tss->Delete();
 }
 
+/**
+ * \brief Sets in the File the TransferSyntax to 'Explicit VR Little Endian"   
+ */ 
 void FileHelper::SetWriteFileTypeToExplicitVR()
 {
    std::string ts = Util::DicomString( 
 void FileHelper::SetWriteFileTypeToExplicitVR()
 {
    std::string ts = Util::DicomString( 
@@ -1017,7 +1057,6 @@ void FileHelper::SetWriteFileTypeToExplicitVR()
 
    DataEntry *tss = CopyDataEntry(0x0002,0x0010);
    tss->SetString(ts);
 
    DataEntry *tss = CopyDataEntry(0x0002,0x0010);
    tss->SetString(ts);
-
    Archive->Push(tss);
    tss->Delete();
 }
    Archive->Push(tss);
    tss->Delete();
 }
@@ -1032,7 +1071,6 @@ void FileHelper::SetWriteFileTypeToImplicitVR()
 
    DataEntry *tss = CopyDataEntry(0x0002,0x0010);
    tss->SetString(ts);
 
    DataEntry *tss = CopyDataEntry(0x0002,0x0010);
    tss->SetString(ts);
-
    Archive->Push(tss);
    tss->Delete();
 }
    Archive->Push(tss);
    tss->Delete();
 }
@@ -1184,11 +1222,15 @@ 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.
+   FILTERED_IMAGE
 -3) user created a new image, using existing images (eg MIP, MPR, cartography image)
 -3) user created a new image, using existing images (eg MIP, MPR, cartography image)
--4) user anonymized an image without processing the pixels.
-
+   CREATED_IMAGE
+-4) user modified/added some tags *without processing* the pixels (anonymization..
+   UNMODIFIED_PIXELS_IMAGE
+   
 gdcm::FileHelper::CheckMandatoryElements() deals automatically with these cases.
 
 1)2)3)4)
 gdcm::FileHelper::CheckMandatoryElements() deals automatically with these cases.
 
 1)2)3)4)
@@ -1205,17 +1247,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]
@@ -1238,14 +1278,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 
@@ -1253,23 +1290,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.   
@@ -1320,14 +1350,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 )
    {
@@ -1348,7 +1379,7 @@ void FileHelper::CheckMandatoryElements()
    // Always modify the value
    // Push the entries to the archive.
       CopyMandatoryEntry(0x0002,0x0000,"0");
    // Always modify the value
    // Push the entries to the archive.
       CopyMandatoryEntry(0x0002,0x0000,"0");
+
       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);
@@ -1356,21 +1387,24 @@ 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"); 
+      }
       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");
+      }
+      
    // 'Media Storage SOP Instance UID'   
       CopyMandatoryEntry(0x0002,0x0003,sop);
       
    // 'Implementation Class UID'
    // FIXME : in all examples we have, 0x0002,0x0012 is not so long :
    // 'Media Storage SOP Instance UID'   
       CopyMandatoryEntry(0x0002,0x0003,sop);
       
    // 'Implementation Class UID'
    // FIXME : in all examples we have, 0x0002,0x0012 is not so long :
-   //         semms to be Root UID + 4 digits (?)
+   //         seems to be Root UID + 4 digits (?)
       CopyMandatoryEntry(0x0002,0x0012,Util::CreateUniqueUID());
 
    // 'Implementation Version Name'
       CopyMandatoryEntry(0x0002,0x0012,Util::CreateUniqueUID());
 
    // 'Implementation Version Name'
@@ -1379,6 +1413,20 @@ void FileHelper::CheckMandatoryElements()
       CopyMandatoryEntry(0x0002,0x0013,version);
    }
 
       CopyMandatoryEntry(0x0002,0x0013,version);
    }
 
+   // --------------------- For DataSet ---------------------
+      
+   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");      
+   }
+   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");      
+   }   
+
    // Push out 'LibIDO-special' entries, if any
    Archive->Push(0x0028,0x0015);
    Archive->Push(0x0028,0x0016);
    // Push out 'LibIDO-special' entries, if any
    Archive->Push(0x0028,0x0015);
    Archive->Push(0x0028,0x0016);
@@ -1440,22 +1488,26 @@ void FileHelper::CheckMandatoryElements()
    
    // '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);
+      CheckMandatoryEntry(0x0018,0x1164,pixelSpacing);
    
    // Samples Per Pixel (type 1) : default to grayscale 
    CheckMandatoryEntry(0x0028,0x0002,"1");
    
    // Samples Per Pixel (type 1) : default to grayscale 
    CheckMandatoryEntry(0x0028,0x0002,"1");
-   
+
    // --- Check UID-related Entries ---
 
    // --- Check UID-related Entries ---
 
-   // If 'SOP Class UID' exists ('true DICOM' image)
+
+   if ( ContentType != USER_OWN_IMAGE) // when it's not a user made image
+   { 
+    // If 'SOP Class UID' exists ('true DICOM' image)
    // we create the 'Source Image Sequence' SeqEntry
    // to hold informations about the Source 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 )
-   {
+  
+      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) );
       // Create 'Source Image Sequence' SeqEntry
       SeqEntry *sis = SeqEntry::New (
             Global::GetDicts()->GetDefaultPubDict()->GetEntry(0x0008, 0x2112) );
@@ -1483,47 +1535,21 @@ void FileHelper::CheckMandatoryElements()
       Archive->Push(sis);
       sis->Delete();
  
       Archive->Push(sis);
       sis->Delete();
  
-      // 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");
-
-   }
+      // 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");    
+      }
+   }    
 
    // 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);
 
    // 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)
 
 
+   if ( ContentType == USER_OWN_IMAGE)
+   {
        // Conversion Type.
        // Other possible values are :
        // See PS 3.3, Page 408
        // Conversion Type.
        // Other possible values are :
        // See PS 3.3, Page 408
@@ -1536,12 +1562,19 @@ 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"); // 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());
 
    // new value for 'SOP Instance UID'
    //SetMandatoryEntry(0x0008,0x0018,Util::CreateUniqueUID());
 
@@ -1602,11 +1635,14 @@ void FileHelper::CheckMandatoryElements()
    gdcm::Orientation *o = gdcm::Orientation::New();
    std::string ori = o->GetOrientation ( FileInternal );
    o->Delete();
    gdcm::Orientation *o = gdcm::Orientation::New();
    std::string ori = o->GetOrientation ( FileInternal );
    o->Delete();
-   if (ori != "\\" )
+   if (ori != "\\" && ori != GDCM_UNFOUND)
       CheckMandatoryEntry(0x0020,0x0020,ori);
    else   
       CheckMandatoryEntry(0x0020,0x0020,"");
       CheckMandatoryEntry(0x0020,0x0020,ori);
    else   
       CheckMandatoryEntry(0x0020,0x0020,"");
-   
+
+   // Default Patient Position to HFS
+   CheckMandatoryEntry(0x0018,0x5100,"HFS");
+
    // Modality : if missing we set it to 'OTher'
    CheckMandatoryEntry(0x0008,0x0060,"OT");
 
    // Modality : if missing we set it to 'OTher'
    CheckMandatoryEntry(0x0008,0x0060,"OT");
 
@@ -1630,21 +1666,11 @@ void FileHelper::CheckMandatoryElements()
 
    // Referring Physician's Name :'type 2' entry -> must exist, value not mandatory
    CheckMandatoryEntry(0x0008,0x0090,"");
 
    // Referring Physician's Name :'type 2' entry -> must exist, value not mandatory
    CheckMandatoryEntry(0x0008,0x0090,"");
-   
-   // Remove some inconstencies (probably some more will be added)
 
 
-   // 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)
@@ -1658,7 +1684,8 @@ 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)
@@ -1762,7 +1789,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;