]> 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.
 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
 
 ------------------------------------------------------------------------
 
 HTH
 Jean-Pierre Roux
 
 ------------------------------------------------------------------------
+
 0) Intro
 0) Intro
+========
 1) How to Read a DICOM file
 1) How to Read a DICOM file
+===========================
 1-1) using raw C++
 1-1-1) A single 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-1-2) A File Set
+
 1-2) using VTK
 1-2-1) A single file
 1-2-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-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
 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) 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-1-2) A File Set
+
 2-2) using VTK
 2-2) using VTK
+
 2-3) using ITK
 
 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
 ----------------------------------------------------------------------------
 
 0) Intro
---------
+========
 
 
-If you are not familiar with DICOM files , use :
+If you are not familiar with DICOM files, use :
 
 PrintFile filein=yourDicomFile.dcm
 
 
 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 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
 
 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
 
 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
 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) 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();
 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.
 
 
 Check if the file is gdcm-readable.
 
@@ -148,11 +267,24 @@ Check some fields, e.g
 
 (or whatever you feel like ...)
 
 
 (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, ...) 
 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);
 
            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();
 
            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,
 - "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 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 :-(
 
 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: 
 
 
 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();
 
            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
 -----------------
 
 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.
 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++) {
 
     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 );
 
 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 :
   
 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();
   
   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.
   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++) {
 
     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?)
     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.
    
 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,
 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' 
 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 ! - 
  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:
  
 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:
    
 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 :   
    
 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
 
  
 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.
 
 --------------
 a vtkGdcmReader() method ( derived from vtkReader() ) is available.
 
-
-
 1-2-1) A single file
 --------------------
 
    vtkGdcmReader *reader = vtkGdcmReader::New();
    reader->SetFileName( yourDicomFilename );      
 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();
    reader->Update();
    vtkImageData* ima = reader->GetOutput();
-   int* Size = ima->GetDimensions();   
+   int* Size = ima->GetDimensions(); 
+     
  // -> Enjoy it.     
 
 1-2-2) A File Set
  // -> 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] );     
    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();
    reader->Update();
    vtkImageData* ima = reader->GetOutput();
    int* Size = ima->GetDimensions();
+   
  // -> Enjoy it.
  
  Warning : The first file is assumed to be the reference file.
  // -> 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
  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);
       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
 e.g.
 vtkgdcmSerieViewer dirname=Dentist mirror
 vtkgdcmSerieViewer dirname=Dentist reverse
@@ -461,36 +673,11 @@ is wrapable by swig.
 2) How to write DICOM file
 ==========================
 
 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) 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 :
 
 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
         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
         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
         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
         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
         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
 
 //--> Create a gdcm::FileHelper
-
        gdcm::FileHelper *fileH = gdcm::FileHelper::New(file);
        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)
 
       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!
 
 
 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
 --------------
 
 
 2-2) using VTK
 --------------
 
+/// \todo : write it!
+
 2-2-1) A single file
 --------------------
 
 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
 // 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.
 
    // 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.
    // 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
 -----------------
 
 2-2-2) A File Set
 -----------------
@@ -592,5 +875,208 @@ vtkSetMacro(GdcmFile, gdcm::File *);
 --------------
 /// \todo : write it!
 
 --------------
 /// \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>
 }}}
 </pre>