]> Creatis software - gdcm.git/blobdiff - Doc/Website/HowToUseGdcm.html
I don't like warnings!
[gdcm.git] / Doc / Website / HowToUseGdcm.html
index 5a4f05a013638e1b93c6cc2fe79422587bf31b1e..de92c7be36f788fc14617c2a15b78fd041af468c 100755 (executable)
@@ -4,39 +4,82 @@ This is a vi-able/notepad-able document to (try to) explain in a few words
 how to use efficently gdcm.
 -->Feel free to send/add your comments/suggestions/modifications.
 -->Don't try to 'beautify' this page.
-(I plane to rewrite it, and add it to the gdcm site as soon as 
-there is enough 'content' within it)
+(I plane to rewrite it in html, as soon as there is enough 'content' within it)
 
 HTH
 Jean-Pierre Roux
 
 ------------------------------------------------------------------------
+
 0) Intro
+========
 1) How to Read a DICOM file
+===========================
 1-1) using raw C++
 1-1-1) A single file
+1-1-1-1) Deal with the file header
+1-1-1-2) Load the 'pixels' in memory
+1-1-1-3) Get the value of a single Dicom DataElement 
+1-1-1-4) Get the values within a Dicom Sequence  
 1-1-2) A File Set
+
 1-2) using VTK
 1-2-1) A single file
 1-2-2) A File Set
+
 1-3) using ITK
 1-3-1) A single file
 1-3-2) A File Set
+
 1-4) Retrictions for Python users
 
 2) How to write DICOM file
+==========================
 2-1) using raw C++
 2-1-1) A single file
+2-1-1-1) Deal with optional DataElements
+2-1-1-1-1) Add a single Dicom DataElement // TODO
+2-1-1-1-2) Add a Dicom Sequence           // TODO
 2-1-2) A File Set
+
 2-2) using VTK
+
 2-3) using ITK
 
+2-4) Retrictions for Python users
+
+3) DICOMDIR
+===========
+3-1) How to read a DICIMDIR
+3-2) How to modifiy a DICOMDIR
+3-3) How to create a DICOMDIR
+
+4) Some 'Command line' utilities
+================================
+4-) PrintFile
+4-) exSerieHelper
+4-) exXCoherentFileSet
+
+4-) AnonymizeNoLoad
+4-) AnonymizeMultiPatient
+4-) AnonymizeDicomDir
+
+4-) ReWrite
+4-) RawToDicom
+4-) exMoveImagesToSingleSerieUID
+
+4-) vtkgdcmViewer2
+4-) vtkgdcmSerieViewer2
+
+4-) PrintDicomDir
+4-) MakeDicomDir
+
 ----------------------------------------------------------------------------
 
 0) Intro
---------
+========
 
-If you are not familiar with DICOM files , use :
+If you are not familiar with DICOM files, use :
 
 PrintFile filein=yourDicomFile.dcm
 
@@ -49,6 +92,8 @@ D 0018|602c [FD]   [Physical Delta X][0]
 D 0020|0013 [IS]   [Instance Number] [5 ]
 D 0028|0010 [US]   [Rows]            [480]
 D 0011|0010 [  ]   [gdcm::Unknown]   [DLX_PATNT_01]
+D 0028|1222 [OW]   [Segmented Green Palette Color Lookup Table Data]
+                                 ===> [gdcm::Binary data loaded;length = 113784]
 
 0008|0021 : 'Group Number'|'Element Number' -> The Element identifier
 Have a look at gdcm/Dicts/dicomV3.dic for the whole list of Elements
@@ -106,7 +151,70 @@ S 0018|6011 [SQ]                       [Sequence of Ultrasound Regions]
 
 0018|6011 is a 'Sequence' (SQ), composed of various Sequence Items(SQItem)
 Each SQItem is a set of Elements (an Element may be a DataElement (D) or a
-Sequence (S), recursively.
+Sequence (S), recursively, within any level of embedding :
+
+S 0029|263d [SQ]                                                                   []
+   |  --- SQItem number 0
+   | D fffe|e000 [UL]                                                              [Item ]
+   | D 0008|0000 [UL]                                                       [Group Length] [12]
+   | D 0008|0001 [UL]                                               [Length to End (RET) ] [28776]
+   | D 0029|0000 [UL]                                                       [Group Length] [28764]
+   | D 0029|002a [LO]                                                    [Private Creator] [SPI-P-Private_ICS Release 1;6 ]
+   | D 0029|2a02 [LO]                                                                   [] [PERFUSION_MR_T2STAR_GAMMA_VARIATE_ANALYSER]
+   | S 0029|2a06 [SQ]                                                                   []
+   |    |  --- SQItem number 0
+   |    | D fffe|e000 [UL]                                                              [Item ]
+   |    | D 0008|0000 [UL]                                                       [Group Length] [12]
+   |    | D 0008|0001 [UL]                                               [Length to End (RET) ] [20]
+   |    | D fffe|0000 [UL]                                                       [Group Length]
+   |    |  --- SQItem number 1
+   |    | D fffe|e000 [UL]                                                              [Item ]
+   |    | D 0008|0000 [UL]                                                       [Group Length] [12]
+   |    | D 0008|0001 [UL]                                               [Length to End (RET) ] [194]
+   |    | D 0029|0000 [UL]                                                       [Group Length] [182]
+   |    | D 0029|002a [LO]                                                    [Private Creator] [SPI-P-Private_ICS Release 1;6 ]
+   |    | S 0029|2a07 [SQ]                                                                   []
+   |    |    |  --- SQItem number 0
+   |    |    | D fffe|e000 [UL]                                                              [Item ]
+   |    |    | D 0008|0000 [UL]                                                       [Group Length] [12]
+   |    |    | D 0008|0001 [UL]                                               [Length to End (RET) ] [100]
+   |    |    | D 0029|0000 [UL]                                                       [Group Length] [88]
+   |    |    | D 0029|002a [LO]                                                    [Private Creator] [SPI-P-Private_ICS Release 1;6 ]
+   |    |    | D 0029|2a0a [US]                                                                   [] [1]
+   |    |    | D 0029|2a0b [US]                                                                   [] [2]
+   |    |    | D 0029|2a0c [US]                                                                   [] [2]
+   |    |    | D 0029|2a0d [US]                                                                   [] [1]
+   |    |    | D 0029|2a10 [US]                                                                   [] [1]
+   |    |    | S 0029|2a2e [SQ]                                                                   []
+   |    |    |    |  --- SQItem number 0
+   |    |    |    | D fffe|e000 [UL]                                                              [Item ]
+   |    |    |    | D 0008|0000 [UL]                                                       [Group Length] [12]
+   |    |    |    | D 0008|0001 [UL]                                               [Length to End (RET) ] [2266]
+   |    |    |    | D 0029|0000 [UL]                                                       [Group Length] [2254]
+   |    |    |    | D 0029|0025 [LO]                                                    [Private Creator] [SPI-P-Private_ICS Release 1;1 ]
+   |    |    |    | D 0029|0027 [LO]                                                    [Private Creator] [SPI-P-Private_ICS Release 1;3 ]
+   |    |    |    | D 0029|0028 [LO]                                                    [Private Creator] [SPI-P-Private_ICS Release 1;4 ]
+   |    |    |    | D 0029|2500 [SL]                                                                   [] [43]
+   |    |    |    | D 0029|256b [FD]                                                                   [] [0.5]
+   |    |    |    | D 0029|2700 [LO]                                                                   [] [L1]
+   |    |    |    | D 0029|276a [FL]                                                                   [] [0.35]
+   |    |    |    | S 0029|27c0 [SQ]                                                                   []
+   |    |    |    |    |  --- SQItem number 0
+   |    |    |    |    | D fffe|e000 [UL]                                                              [Item ]
+   |    |    |    |    | D 0008|0000 [UL]                                                       [Group Length] [12]
+   |    |    |    |    | D 0008|0001 [UL]                                               [Length to End (RET) ] [110]
+   |    |    |    |    | D 0029|0000 [UL]                                                       [Group Length] [98]
+   |    |    |    |    | D 0029|0027 [LO]                                                    [Private Creator] [SPI-P-Private_ICS Release 1;3 ]
+   |    |    |    |    | D 0029|27b0 [SL]                                                                   [] [0]
+   |    |    |    |    | D 0029|27b1 [FL]                                                                   [] [0]
+   |    |    |    |    | D 0029|27b2 [FL]                                                                   [] [0]
+   |    |    |    |    | D 0029|27b4 [FL]                                                                   [] [0]
+   |    |    |    |    | D 0029|27b9 [FL]                                                                   [] [1]   
+   | S 0029|2a14 [SQ]                                                                   []
+   |    |  --- SQItem number 0
+   |    | D fffe|e000 [UL]                                                              [Item ]
+   |    | D 0008|0000 [UL]                                                       [Group Length] [12]
+   
 Probabely, you'll never have to deal with Sequences (hope so!).
 
 1) How to Read a DICOM File
@@ -118,18 +226,29 @@ Probabely, you'll never have to deal with Sequences (hope so!).
 1-1-1) A single file
 --------------------
 
+1-1-1-1) Deal with the file header
+
 The first step is to load the file header :
 
            gdcm::File *f = new gdcm::File();
-                  f->SetLoadMode(NO_SEQ);            | depending on what
-                  f->SetLoadMode(NO_SHADOW);         | you want *not* 
-                  f->SetLoadMode(NO_SEQ | NO_SHADOW);| to load from the
-                  f->SetLoadMode(NO_SHADOWSEQ);      | target file
-            f->SetFileName(fileName);
-            f->Load( );
-    
-Except if someone told you -he knows the file headers are bugged-, 
-do *not* use SetLoadMode().
+                  f->SetLoadMode(LD_NOSEQ);              | depending on what
+                  f->SetLoadMode(LD_NOSHADOW);           | you want *not* 
+                  f->SetLoadMode(LD_NOSEQ | LD_NOSHADOW);| to load from the
+                  f->SetLoadMode(LD_NOSHADOWSEQ);        | target file
+           f->SetFileName(fileName);
+           f->Load( );
+
+Note :
+The 'long' Data Element (>4096 char) are not loaded by default
+You may modify this default length :
+           f->SetMaxSizeLoadEntry(int yourOwnMaxSize);
+Or ask to force the loading of given Data Elements, whatever their size is:  
+            f->AddForceLoadElement (uint16_t group, uint16_t elem);
+before calling gdcm::File::Load();
+
+Note :
+Except if you are really aware about it, do *not* use SetLoadMode().
+LD_ALL is the default.
 
 Check if the file is gdcm-readable.
 
@@ -148,11 +267,24 @@ Check some fields, e.g
 
 (or whatever you feel like ...)
 
+1-1-1-2) Load the 'pixels' in memory
+
 Next step is to load the pixels in memory.
 Uncompression (JPEG lossless, JPEG lossy, JPEG 2000, RLE, ...) 
-is automatically performed if necessary.
+will be automatically performed if necessary.
+
+You first have to create a 'File Helper'
 
            gdcm::FileHelper *fh = gdcm::FileHelper::New(f);
+
+In some images,(where BitsAllocated=16, BitsUsed=8), 
+the 'unused bits' are actually ... used for storing 'overlays'.
+(e.g. : Patient / Aquisition / Institution informations, or drawings ...)
+It's up to you to decide whether you want or not to load the overlays.
+(Probabely, if you want to post-process the images, you dont' want!)
+
+           fh->SetKeepOverlays(true);  // default is : false
+
            void *imageData = fh->GetImageDataRaw();
            uint32_t dataSize = fh->GetImageDataRawSize();
 
@@ -170,18 +302,20 @@ Possible values are :
 - "16S"   signed 16 bit,
 - "32U" unsigned 32 bit,
 - "32S"   signed 32 bit,
-
+- (NEITHER 'float' NOR 'double' pixels in DICOM!)
    
-           int dimX = f->GetXcurrentFileName[i]Size();
+           int dimX = f->GetXSize();
            int dimY = f->GetYSize();
-           int dimZ = f->GetZSize();
-           int dimT = f->GetTSize();
-
-Now, you can enjoy your image !
+           int dimZ = f->GetZSize(); // meaningfull only for 'Volumes' or 'multiframe files'
+           int dimT = f->GetTSize(); // meaningfull only for 4D objects (?)
 
 Sometimes, you deal with 'colour' images :-(
-They may be stored, on disc, as RGB pixels, RGB planes, YBR pixels, YBR planes
-Grey level images + LUT.
+They may be stored, on disc, as :
+     RGB pixels, 
+     RGB planes, 
+     YBR pixels, 
+     YBR planes
+     Grey level images + LUT.
 
 You'll get an 'RGB Pixels' image in memory if you use: 
 
@@ -189,6 +323,54 @@ You'll get an 'RGB Pixels' image in memory if you use:
            void *imageData = fh->GetImageData();
            uint32_t dataSize = fh->GetImageDataSize();
 
+If you don't want to convert a "Grey level images + LUT" into "RGB Pixel image" use
+           gdcm::FileHelper *fh = gdcm::FileHelper::New(f);
+           void *imageData = fh->GetImageDataRaw();
+           uint32_t dataSize = fh->GetImageDataRawSize();
+   
+Now, you can enjoy your image !   
+
+1-1-1-3) Get the value of a single Dicom DataElement 
+
+1-1-1-3-1) as a std::string
+
+- some DataEntries are 'human readable' (those whose VR is AE, DA, DS, PN, SH, TM)
+  Get their value using group number-element number :
+  std::string patientName = f->GetEntryString(0x0010,0x0010);
+  
+- Some DataEntries are stored with their own binary representation, but maybe you feel like 
+  to get them in a 'human readable' form (those whose VR is FL, FD, SL, SS, UL, US)
+  Get their value using group number-element number : 
+  std::string rowNumber =f->GetEntryString(0x0028, 0x0010);// nb of Rows
+  
+  (of course, the very often used DataEntries have their own accessors :
+  e.g. GetXsize, GetYSize, GetSpacing, GetImageOrientationPatient, GetImagePositionPatient,
+       GetRescaleSlope, GetRescaleIntercept, GetNumberOfScalarComponents, etc -see gdcmFile.h-)
+  
+
+1-1-1-3-3) as a void* pointer
+- Some DataEntries are stored with their own binary representation, and you want to get them 'as they are'.
+  You will have to cast them, according to the knowledge you have about them.
+  LutRedData = (uint8_t*)f->GetEntryBinArea( 0x0028, 0x1201 ); 
+   
+1-1-1-4) Get the value(s) within a Dicom Sequence           
+
+Actually, a 'Dicom Sequence' is composed of a list a 'Sequence Items',
+each Sequence Item is a set of DataElement (that can be Dicom Sequences, recursively).
+You have to get the Sequence element, to get its number of Sequence items, to iterate on each one.
+e.g.:
+
+SeqEntry *seqEntry = f->GetSeqEntry(0x3006,0x0020); //Structure Set ROI sequence
+unsigned int n = seqEntry->GetNumberOfSQItems();    // useless : just to see !
+currentItem = seqEntry->GetFirstSQItem(); // Get the first ROI
+while (currentItem != NULL) {
+   std::string roiName = currentItem->GetEntryString(0x3006,0x0026);  //ROI name
+   std::string roiDescr = currentItem->GetEntryString(0x3006,0x0028); //ROI description
+   ...
+   // do what you want with the current ROI
+   currentItem = seqEntry->GetNextSQItem(); // Get the next ROI
+}
+
 
 1-1-2) A File Set
 -----------------
@@ -201,7 +383,7 @@ of images, laying in a Directories tree-like structure, you don't know anything
 about the Patients, and so on)
 
 A class gdcm::SerieHelper is designed to help solving this problem.
-Use it as follows.
+Use it as follows :
 
     gdcm::SerieHelper *sh = gdcm::SerieHelper::New();
     while (int i=0; i < nbOfFiles; i++) {
@@ -214,7 +396,36 @@ You can also pass a 'root directory', and ask or not for recursive parsing.
 
 Files are 'splitted' into as many 'Single Serie UID File Set' 
   as Series Instance UID ( 0020|000e );
-  
+
+// -------- skip this one, for a first reading ! -----------
+
+Sometimes, the Serie UID is not enough to disseminate properly the images.
+We may want to disseminate into multiple sub series when needed.
+
+Use :
+void SerieHelper::SetUseSeriesDetails(bool s);
+   /// This function will add the following DICOM tag as being part of a
+   /// 'fake' uid. :
+   /// 0020 0011 Series Number
+   /// 0018 0024 Sequence Name
+   /// 0018 0050 Slice Thickness
+   /// 0028 0010 Rows
+   /// 0028 0011 Columns 
+
+If it's not enough for you, use :    
+void SerieHelper::AddSeriesDetail(uint16_t group, uint16_t elem, bool convert);
+
+std::string SerieHelper::CreateUniqueSeriesIdentifier(gdcm::File *inFile);
+void SerieHelper::CreateDefaultUniqueSeriesIdentifier();
+
+You may also create a "tokenizable' File Identifier of your own, using :
+void SerieHelper::AddSeriesDetail(uint16_t group, uint16_t elem, bool convert);
+and
+std::string SerieHelper::CreateUserDefinedFileIdentifier(gdcm::File *inFile);
+and use it as you feel like.
+
+// ------------ Resume reading, here !--------------------
 If you want to 'order' the files within each 'Single Serie UID File Set'
 (to build a volume, for instance), use :
   
@@ -238,8 +449,9 @@ If you want to 'order' the files within each 'Single Serie UID File Set'
   or back to Direct Order 
   sh->SetSortOrderToDirect();
   
-  If, for any reason of is own, user already get the file headers,
+  If, for any reason of his own, user already get the file headers,
   he may add the gdcm::File (instead of the file name) to the SerieHelper.
+  (Sorry, not available in Python)
 
     gdcm::SerieHelper *sh = gdcm::SerieHelper::New();
     while (int i=0; i < nbOfFiles; i++) {
@@ -276,8 +488,6 @@ e.g.
     while (int i=0; i < nbOfFiles; i++) { 
     ...
 User wants to deal only with Female patient, any Modality but MR (why not?)
-
-
    
 Maybe user knows there are several images with the same position
 and *no dicom field* may discriminates them.
@@ -288,7 +498,7 @@ He wants to drop the 'duplicate images'
 Sometimes the previous stuff is *not enough* !
 
 Within a SingleSerieUIDFileSet, you can have have various orientations,
-or various positions, at various times. (not only various position , at a single
+or various positions, at various times. (not only various positions, at a single
 time, for a single orientation).
 
 User may consider that dealing only with the 'Series Instance UID' 
@@ -306,16 +516,16 @@ gdcm::FileList *l = s->GetFirstSingleSerieUIDFileSet(); // or what you want
  The following methods must be called by user, depending on 
  what *he* wants to do, at application time.
   - *he* only  knows what his Series contain ! - 
- They return a std::map of Filesets (actually : std::vector of gdcm::File*).
+ They return a std::map of Filesets (actually : a std::map of std::vector<gdcm::File* >).
  
 He may ask for 'splitting' on the Orientation:
-           xcm = s->SplitOnOrientation(l);
+           gdcm::XCoherentFileSetmap xcm = s->SplitOnOrientation(l);
    
 He may ask for 'splitting' on the Position:
-           xcm = s->SplitOnPosition(l);
+           gdcm::XCoherentFileSetmap xcm = s->SplitOnPosition(l);
    
 He may ask for 'splitting' on the any DataElement you feel like :   
-           xcm = s->SplitOnTagValue(l, groupelem[0],groupelem[1]);
+           gdcm::XCoherentFileSetmap xcm = s->SplitOnTagValue(l, group,elem);
 
  
 He can now work on each 'X Coherent File Set' within the std::map
@@ -338,17 +548,17 @@ for (gdcm::XCoherentFileSetmap::iterator i = xcm.begin();
 --------------
 a vtkGdcmReader() method ( derived from vtkReader() ) is available.
 
-
-
 1-2-1) A single file
 --------------------
 
    vtkGdcmReader *reader = vtkGdcmReader::New();
    reader->SetFileName( yourDicomFilename );      
-   reader->SetLoadMode( yourLoadMode); // See C++ part 
+   reader->SetLoadMode( yourLoadMode );   // See C++ part 
+   reader->SetKeepOverlays( true/false ); // See C++ part    
    reader->Update();
    vtkImageData* ima = reader->GetOutput();
-   int* Size = ima->GetDimensions();   
+   int* Size = ima->GetDimensions(); 
+     
  // -> Enjoy it.     
 
 1-2-2) A File Set
@@ -360,10 +570,12 @@ feel like:
    vtkGdcmReader *reader = vtkGdcmReader::New();
    for(int i=1; i< yourNumberOfFiles; i++)
          reader->AddFileName( yourTableOfFileNames[i] );     
-   reader->SetLoadMode( yourLoadMode); // See C++ part 
+   reader->SetLoadMode( yourLoadMode );   // See C++ part 
+   reader->SetKeepOverlays( true/false ); // See C++ part     
    reader->Update();
    vtkImageData* ima = reader->GetOutput();
    int* Size = ima->GetDimensions();
+   
  // -> Enjoy it.
  
  Warning : The first file is assumed to be the reference file.
@@ -371,7 +583,7 @@ feel like:
  and replaced by a black image ! 
  
       User is allowed to pass a Pointer to a function of his own
-      to allow modification of pixel order (i.e. : Mirror, TopDown, )
+      to allow modification of pixel order (i.e. : Mirror, UpsideDown, )
       to gdcm::FileHeleper, using SetUserFunction(userSuppliedFunction)
 
       described as : void userSuppliedFunction(uint8_t *im, gdcm::File *f);
@@ -443,7 +655,7 @@ methods : (see 1-1-2 for more details)
 //----------------
 
 
-You can see a full example in vtk/vtkgdcmSerieViewer.cxx
+You can see a full example in vtk/vtkgdcmSerieViewer2.cxx
 e.g.
 vtkgdcmSerieViewer dirname=Dentist mirror
 vtkgdcmSerieViewer dirname=Dentist reverse
@@ -461,36 +673,11 @@ is wrapable by swig.
 2) How to write DICOM file
 ==========================
 
-   // gdcm cannot guess how user built his image 
-   //  (and therefore cannot be clever about some Dicom fields)
-   // It's up to the user to tell gdcm what he did.
-   // -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.
-   // FILTERED_IMAGE
-   // -3) user created a new image, using existing a set of 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
-   //(see gdcmFileHelper.h for more explanations)
-   
-   // User is allowed to use the following methods:
-   
-   void SetContentTypeToUserOwnImage()         
-                    {SetContentType(VTK_GDCM_WRITE_TYPE_USER_OWN_IMAGE);}
-   void SetContentTypeToFilteredImage()        
-                    {SetContentType(VTK_GDCM_WRITE_TYPE_FILTERED_IMAGE);}
-   void SetContentTypeToUserCreatedImage()     
-                    {SetContentType(VTK_GDCM_WRITE_TYPE_CREATED_IMAGE);}
-   void SetContentTypeToUnmodifiedPixelsImage()
-                    {SetContentType(VTK_GDCM_WRITE_TYPE_UNMODIFIED_PIXELS_IMAGE);}
-
 2-1) using raw C++
 ------------------
+
+2-1-1) A single file
+--------------------
 In C++, if you have already the pixels in main memory, 
 you just have to process as follow :
 
@@ -500,7 +687,7 @@ you just have to process as follow :
         std::ostringstream str;
 
 // --> Set the mandatory fields
-// Set the image size
+  // Set the image size
         str.str("");
         str << sizeY;
         file->InsertEntryString(str.str(),0x0028,0x0010,"US"); // Rows
@@ -510,7 +697,7 @@ you just have to process as follow :
         str.str("");
         str << sizeZ;
         file->InsertEntryString(str.str(),0x0028,0x0008, "IS"); // Nbr of Frames
-          // Set the pixel type
+  // Set the pixel type
         str.str("");
         str << componentSize; //8, 16, 32
         file->InsertEntryString(str.str(),0x0028,0x0100,"US"); // Bits Allocated
@@ -530,58 +717,154 @@ you just have to process as follow :
         file->InsertEntryString(str.str(),0x0028,0x0002, "US"); // Samples per Pixel
 
 //--> Set Optional fields
-//(patient name, patient ID, modality, or what you want
-//Have look at gdcm/Dict/dicomV3.dic to see what are the various DICOM fields)
+      see further how to deal with optional fields
 
 //--> Create a gdcm::FileHelper
-
        gdcm::FileHelper *fileH = gdcm::FileHelper::New(file);
-       fileH->SetImageData((unsigned char *)imageData,size);
-       
-//casting as 'unsigned char *' is just to avoid warnings.
-// It doesn't change the values.
 
-      fileH->SetWriteModeToRaw();
-      fileH->SetWriteTypeToDcmExplVR();
+//--> Tell the FileHelper what you did for creating the image:
+
+      // gdcm cannot guess how user built his image 
+      //  (and therefore cannot be clever about some Dicom fields)
+      // It's up to the user to tell gdcm what he did.
+      // -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.
+      // FILTERED_IMAGE
+      // -3) user created a new image, using existing a set of 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
+      //(see gdcmFileHelper.h for more explanations)
+
+      // Use :
+      
+      fileH->SetContentType(GDCM_NAME_SPACE::USER_OWN_IMAGE);
+      fileH->SetContentType(GDCM_NAME_SPACE::FILTERED_IMAGE);
+      fileH->SetContentType(GDCM_NAME_SPACE::CREATED_IMAGE);
+      fileH->SetContentType(GDCM_NAME_SPACE::UNMODIFIED_PIXELS_IMAGE);
+      
+      // depending on what you did before!
+
+//--> Set the compression type : 
+      fileH->SetWriteTypeToJPEG();      // lossless compression        
+      fileH->SetWriteTypeToJPEG2000();  // lossless compression 
+      fileH->SetWriteTypeToDcmExplVR(); // Explicit Value Representation (no compression)
+      fileH->SetWriteTypeToDcmImplVR(); // Implicit Value Representation (no compression)
+      
+      fileH->SetWriteModeToRaw();       // Probabely you don't want to convert any LUT into RGB pixels ...
+
+//--> Set the Image Data
+       fileH->SetImageData((unsigned char *)imageData,size);
+      // ( Casting as 'unsigned char *' is just to avoid warnings.
+      // It doesn't change the values. )
+      // or
+       fileH->SetUserData((unsigned char *)imageData,size); // performs compression, when required
+      // ( Casting as 'unsigned char *' is just to avoid warnings.
+      // It doesn't change the values. )
+                  
+//-> Write !      
       fileH->Write(fileName.str());
 
 //This works for a single image (singleframe or multiframe)
 
-// If you deal with a Serie of images, it up to you to tell gdcm, for each image,
-// what are the values of
-// 0020 0032 DS 3 Image Position (Patient)
-// 0020 0037 DS 6 Image Orientation (Patient) 
+2-1-1-1) Deal with optional DataElements          // TODO : finish it
 
-2-1-1) A single file
---------------------
-/// \todo : write it!
+    Any Data Element may be added (it's up to the user to understand what he is doing!)
+    The supplied methods 'InsertXxx' will create the DataElement or replace it if it already exists.  
+    Have a look at gdcm/Dict/dicomV3.dic to see what are the various DICOM fields, with their VR.
+    
+2-1-1-1-1) Add a single Dicom DataElement          // TODO : finish it
 
+   use :
+   DataEntry * File::InsertEntryString(std::string const &value,
+                                   uint16_t group, uint16_t elem,
+                                   VRKey const &vr = GDCM_VRUNKNOWN);
+  
+   // (e.g. : patient name, patient ID, ... , or what you want,
+   //  using their Dicom identifier, and 'VR'
+      file->InsertEntryString("MyOwnPatient" ,0x0010,0x0010,"PN"); // 0010 0010 : Patient's Name
+   
+    DataEntry * File:InsertEntryBinArea(uint8_t *binArea, int lgth,
+                                    uint16_t group, uint16_t elem,
+                                    VRKey const &vr = GDCM_VRUNKNOWN);  
+   
+2-1-1-1-2) Add a Dicom Sequence           // TODO : finish it
+   SeqEntry * File::InsertSeqEntry(uint16_t group, uint16_t elem);
+   
 2-1-2) A File Set
 -----------------
 /// \todo : write it!
 
 
+// If you deal with a Serie of images, it up to you to tell gdcm, for each image,
+// what are the values of
+// 0020 0032 DS 3 Image Position (Patient)
+// 0020 0037 DS 6 Image Orientation (Patient)
+
+// You will probabely want that all the images of your file set belong to the same 'Serie'
+
 
 2-2) using VTK
 --------------
 
+/// \todo : write it!
+
 2-2-1) A single file
 --------------------
 
+/// \todo : finish it!
+
 // User of the CVS version of VTK 5 may set some 'Medical Image Properties'
 // Only the predefined DataElements are available :
 // PatientName, PatientID, PatientAge, PatientSex, PatientBirthDate, StudyID
-// It's reasonablt enough for any 'decent use'
-vtkMedicalImageProperties
+// It's reasonably enough for any 'decent use'
+//
+// todo : explain how to use it.
+//vtkMedicalImageProperties
 
    // Aware user is allowed to pass his own gdcm::File *, 
    //  so he may set *any Dicom field* he wants.
-   // (including his own Shadow Eleents, or any gdcm::SeqEntry)
+   // (including his own Shadow Elements, or any gdcm::SeqEntry)
    // gdcm::FileHelper::CheckMandatoryElements() will check inconsistencies,
    // as far as it knows how.
    // Sorry, not yet available under Python.
-vtkSetMacro(GdcmFile, gdcm::File *);
+   
+     vtkSetMacro(GdcmFile, gdcm::File *);
+   
+void vtkGdcmWriter::SetGdcmFile(gdcm::File *);
 
+   // gdcm cannot guess how user built his image 
+   //  (and therefore cannot be clever about some Dicom fields)
+   // It's up to the user to tell gdcm what he did.
+   // -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.
+   // FILTERED_IMAGE
+   // -3) user created a new image, using existing a set of 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
+   //(see gdcmFileHelper.h for more explanations)
+   
+   // User is allowed to use the following methods:
+   
+void vtkGdcmWriter::SetContentTypeToUserOwnImage()                           
+void vtkGdcmWriter::SetContentTypeToFilteredImage()                            
+void vtkGdcmWriter::SetContentTypeToUserCreatedImage()                        
+vtkGdcmWriter::void SetContentTypeToUnmodifiedPixelsImage()
+   
+  // depending on what he did before (see C++ part)
+  
+                      
 
 2-2-2) A File Set
 -----------------
@@ -592,5 +875,208 @@ vtkSetMacro(GdcmFile, gdcm::File *);
 --------------
 /// \todo : write it!
 
+2-4) Retrictions for Python users
+---------------------------------
+/// \todo : write it!
+
+
+3) DICOMDIR /// \todo: finish it!
+===========
+3-1) How to read a DICIMDIR
+3-2) How to modifiy a DICOMDIR
+3-3) How to create a DICOMDIR
+
+
+4) Some 'Command line' utilities  /// \todo: finish it!
+================================
+
+4-) PrintFile
+4-) exSerieHelper
+4-) exXCoherentFileSet
+
+4-) AnonymizeNoLoad
+4-) AnonymizeMultiPatient
+4-) AnonymizeDicomDir
+4-) PatchHeader
+4-) ReWrite
+4-) RawToDicom
+4-) exMoveImagesToSingleSerieUID
+
+4-) vtkgdcmViewer2
+4-) vtkgdcmSerieViewer2
+
+4-) PrintDicomDir
+4-) MakeDicomDir
+
+
+    *   PrintFile
+
+         Displays the header of any kind of ACR-NEMA/PAPYRUS/DICOM File
+         usage: PrintFile {filein=inputFileName|dirin=inputDirectoryName}[level=n]
+                       [forceload=listOfElementsToForceLoad]
+                       [4DLoc= ][dict= privateDirectory]
+                       [ { [noshadowseq] | [noshadow][noseq] } ]
+                       [debug] [warning]
+      level = 0,1,2 : depending on the amount of details user wants to see
+      4DLoc: group-elem(in hexa, no space) of the DataEntry holdind 4thDim
+      listOfElementsToForceLoad : group-elem,g2-e2,... (in hexa, no space)
+                                of Elements to load whatever their length
+      privateDirectory : source file full path name of Shadow Group elems
+      noshadowseq: user doesn't want to load Private Sequences
+      noshadow   : user doesn't want to load Private groups (odd number)
+      noseq      : user doesn't want to load Sequences
+      debug      : user wants to run the program in 'debug mode'
+      warning    : user wants to be warned about any oddity in the File
+      showlut :user wants to display the Palette Color (as an int array)
+
+                          [ { [noshadowseq] | [noshadow][noseq] } ] [debug] [usage]
+                level = 0,1,2 : depending on the amount of details user wants to see
+                noshadowseq: user doesn't want to load Private Sequences
+                noshadow   : user doesn't want to load Private groups (odd number)
+                noseq      : user doesn't want to load Sequences
+                debug      : user wants to run the program in 'debug mode'
+                usage      : user wants to display usage
+         
+
+    * Anonymize
+
+         Anonymizes a full gdcm-readable Dicom image
+                Warning : probably segfaults if pixels are not gdcm readable.
+                          Use AnonymizeNoLoad instead.
+         usage: Anonymize filein=inputFileName fileout=anonymizedFileName [debug][usage]
+                debug    : user wants to run the program in 'debug mode'
+                usage    : user wants to display usage
+        
+
+    * AnonymizeNoLoad
+
+       
+         Anonymizes a gdcm-readable Dicom image even if pixels aren't gdcm readable
+               Warning : the image is overwritten;
+                         to preserve its integrity, use a copy.
+         usage: AnonymizeNoLoad {filein=inputFileName|dirin=inputDirectoryName}
+                                [rubout=listOfPrivateElementsToRubOut]
+                                [ { [noshadowseq] | [noshadow][noseq] } ] [debug]
+                inputFileName : Name of the (single) file user wants to anonymize
+                inputDirectoryName : user wants to anonymize *all* the files
+                                     within the (single Patient!) directory
+                listOfElementsToRubOut : group1-elem1,g2-e2,... (in hexa)
+                                         of extra Elements to rub out
+                noshadowseq: user doesn't want to load Private Sequences
+                noshadow   : user doesn't want to load Private groups (odd number)
+                noseq      : user doesn't want to load Sequences
+                debug      : user wants to run the program in 'debug mode'
+                usage      : user wants to display usage
+         
+
+    * ReWrite
+
+         Reads and rewrites a full gdcm-readable Dicom image
+     (usefull when the file header is not very straight).
+
+ usage: ReWrite filein=inputFileName fileout=outputFileName
+       [keepoverlays] [mode=write mode] [monochrome1]
+       [noshadow] [noseq][debug]
+  --> The following line to 'rubout' a burnt-in Patient name
+       [rubout=xBegin,xEnd,yBegin,yEnd [ruboutvalue=n (<255)] ]
+  --> The 2 following lines, to extract a sub image within some frames
+       [ROI=xBegin,xEnd,yBegin,yEnd]
+       [firstframe=beg] [lastframe=end]
+
+        mode = a (ACR), x (Explicit VR Dicom), r (RAW : only pixels)
+               j (jpeg lossless), 2 (jpeg2000)
+        keepoverlays : user wants to keep ACR-NEMA-like overlays
+        monochrome1 = user wants MONOCHROME1 photom. interp. (0=white)
+        noshadowseq: user doesn't want to load Private Sequences
+        noshadow : user doesn't want to load Private groups (odd number)
+        noseq    : user doesn't want to load Sequences
+        rgb      : user wants to transform LUT (if any) to RGB pixels
+        warning  : developper wants to run the program in 'warning mode'
+        debug    : developper wants to run the program in 'debug mode' a full gdcm-readable Dicom image (compressed Pixels are expanded)
+                         (usefull when the file is not very straight).                  
+        usage: ReWrite filein=inputFileName fileout=anonymizedFileName
+                        [mode=write mode] [rgb]
+                        [ { [noshadowseq] | [noshadow][noseq] } ] [debug] [usage]
+        write mode = a (ACR), x (Explicit VR Dicom), r (RAW : only pixels)
+        rgb        : user wants to transform LUT (if any) into RGB 
+        noshadowseq: user doesn't want to load Private Sequences
+        noshadow   : user doesn't want to load Private groups (odd number)
+        noseq      : user doesn't want to load Sequences
+        debug      : user wants to run the program in 'debug mode'
+        usage      : user wants to display usage
+         
+
+    * PrintDicomDir
+
+         Displays the tree-like structure of a DICOMDIR File
+         usage: PrintDicomDir filein=fileName [detail=n] [level=n] [debug] [usage]
+                detail = 1 : Patients, 2 : Studies, 3 : Series, 4 : Images
+                         5 : Full Content
+                level = 0,1,2 : depending on user (what he wants to see, when detail=5)
+                debug    : user wants to run the program in 'debug mode'
+                usage    : user wants to display usage
+         
+
+    * MakeDicomDir
+
+         Explores recursively the given directory, makes the relevant DICOMDIR
+                and writes it as 'NewDICOMDIR'
+         usage: MakeDicomDir dirname=rootDirectoryName 
+                            [ { [noshadowseq] | [noshadow][noseq] } ] [debug] [usage]
+                noshadowseq: user doesn't want to load Private Sequence
+                noshadow   : user doesn't want to load Private groups (odd number)
+                noseq      : user doesn't want to load Sequences
+                debug      : user wants to run the program in 'debug mode'
+                usage      : user wants to display usage
+         
+
+    * AnonymizeDicomDir
+
+         Anonymizes a gdcm-readable DICOMDIR even when some 'Objects'
+                are not yet taken into account
+                Warning : the DICOMDIR is overwritten; 
+                          to preserve its integrity, use a copy.
+         usage: AnonymizeDicomDir filein=dicomDirName [debug] [usage] [usage]
+                debug    : user wants to run the program in 'debug mode'
+                usage    : user wants to display usage
+         
+
+    * PatchHeader
+
+          Allows aware user to patch a gdcm-parsable image header, without 
+               loading image.
+               Warning : the image(s) is/are overwritten
+                         to preserve image(s) integrity, use a copy.
+               WARNING : *NO CHECK* is performed on the new values.
+                         Use only if you are sure the original values are wrong
+                         *and* your values are right...
+         usage: PatchHeader {filein=inputFileName|dirin=inputDirectoryName}
+                     [ { [size=] | [rows=][columns=] } ] [planes=]
+                     [bitsallocated=] [bitsstored=]
+                     [highbit=] [samplesperpixel=]
+                     [pixelrepresentation=] [samplesperpixel=]
+                     [ { [noshadowseq] | [noshadow][noseq] } ] [debug]
+                                                                                 
+             inputFileName : Name of the (single) file user wants to modify
+             inputDirectoryName : user wants to modify *all* the files
+                                  within the directory
+             newsize         : new size, to overwrite old (wrong) one
+                or
+             rows            : new Rows number,    to overwrite old (wrong) one
+             columns         : new Columns number, to overwrite old (wrong) one
+             planes          : new Planes number,  ...
+             bitsallocated   : new Bits Allocated number,  ...
+             bitsstored      : new Bits Stored number,  ...
+             highbit         : new High Bit number,  ...
+             samplesperpixel : new Samples Per Pixel, ...
+             pixelrepresentation : new Pixel Representation, ...
+                                                                                 
+             noshadowseq: user doesn't want to load Private Sequences
+             noshadow   : user doesn't want to load Private groups (odd number)
+             noseq      : user doesn't want to load Sequences
+             debug      : user wants to run the program in 'debug mode'
+             usage      : user wants to display usage
+         
+
 }}}
 </pre>