]> Creatis software - gdcm.git/blob - Example/AnonymizeReWriteMultiPatient.cxx
fix
[gdcm.git] / Example / AnonymizeReWriteMultiPatient.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: AnonymizeReWriteMultiPatient.cxx,v $
5   Language:  C++
6   Date:      $Date: 2007/11/21 12:53:59 $
7   Version:   $Revision: 1.2 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
12                                                                                 
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18 #include "gdcmDocEntry.h"
19 #include "gdcmDicomDir.h"
20 #include "gdcmDicomDirPatient.h"
21 #include "gdcmDicomDirStudy.h"
22 #include "gdcmDicomDirVisit.h"
23 #include "gdcmDicomDirSerie.h"
24 #include "gdcmDicomDirImage.h"
25 #include "gdcmDirList.h"
26 #include "gdcmDebug.h"
27 #include "gdcmUtil.h"
28 #include "gdcmFile.h"
29 #include "gdcmFileHelper.h"
30
31 #include "gdcmArgMgr.h"
32
33 #include <iostream>
34
35 /**
36   * \brief   Explores recursively the given directory
37   *          orders the gdcm-readable found Files
38   *          according their Patient/Study/Serie/Image characteristics
39   *          and anomymizes (rewrite) them, creates a different name for each Patient.
40   */  
41
42 int main(int argc, char *argv[]) 
43 {
44    START_USAGE(usage)
45    " \n AnonymizeReWriteMultiPatient :\n                                      ",
46    " AnonymizeReWriteMultiPatient a full gdcm-readable Dicom image            ",
47    "         optionnaly, creates the DICOMDIR                                 ",
48    "         Warning : the image is OVERWRITTEN                               ",
49    "                   to preserve image integrity, use a copy.               ",
50    " usage: AnonymizeReWriteMultiPatient dirin=inputDirectoryName  dicomdir   ",
51    "       listOfElementsToRubOut : group-elem,g2-e2,... (in hexa, no space)  ",
52    "                                of extra Elements to rub out              ",
53    "       dicomdir   : user wants to generate a DICOMDIR                     ",
54    "       verbose    : user wants to run the program in 'verbose mode'       ",   
55    "       debug      : user wants to run the program in 'debug mode'         ",   
56    FINISH_USAGE
57    
58
59
60    // ----- Initialize Arguments Manager ------   
61    GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
62   
63    if (argc == 1 || am->ArgMgrDefined("usage")) 
64    {
65       am->ArgMgrUsage(usage); // Display 'usage'
66       delete am;
67       return 0;
68    }
69    const char * name  = am->ArgMgrGetString("dirin");
70    if ( name == NULL )
71    {
72       delete am;
73       return 0;
74    }
75    
76    std::string dirName = name;
77    
78    bool verbose  = ( 0 != am->ArgMgrDefined("verbose") ); 
79    bool dicomdir = ( 0 != am->ArgMgrDefined("dicomdir") );
80    
81    if (am->ArgMgrDefined("debug"))
82       GDCM_NAME_SPACE::Debug::DebugOn();
83
84    int loadMode = GDCM_NAME_SPACE::LD_ALL;
85
86    int rubOutNb;
87    uint16_t *elemsToRubOut = am->ArgMgrGetXInt16Enum("rubout", &rubOutNb);
88  
89    // ----------- if unused Param we give up
90    if ( am->ArgMgrPrintUnusedLabels() )
91    { 
92       am->ArgMgrUsage(usage);
93       delete am;
94       return 0;
95    }
96
97    delete am;  // we don't need Argument Manager any longer
98
99  
100   // ---------------------------------------------------------- 
101   
102
103    // ----- Begin Processing -----
104
105    GDCM_NAME_SPACE::DicomDir *dcmdir;
106
107    // we ask for Directory parsing
108
109    dcmdir = GDCM_NAME_SPACE::DicomDir::New( );
110    dcmdir->SetLoadMode(loadMode);
111    dcmdir->SetDirectoryName(dirName);
112    dcmdir->Load();
113
114    if ( verbose )
115       std::cout << "======================= End Parsing Directory" << std::endl;
116       
117     // ----- Check the result
118     
119    if ( !dcmdir->GetFirstPatient() ) 
120    {
121       std::cout << "No patient found (?!?). Exiting."
122                 << std::endl;
123       dcmdir->Delete();
124       return 1;
125    }
126
127    GDCM_NAME_SPACE::DicomDirPatient *pa;
128    GDCM_NAME_SPACE::DicomDirStudy *st;
129    GDCM_NAME_SPACE::DicomDirSerie *se;
130    GDCM_NAME_SPACE::DicomDirImage *im;
131
132    std::string codedName;
133    std::string codedID;
134    std::string fullFileName;
135    std::string patName;
136    std::string patID;
137         
138    GDCM_NAME_SPACE::File *f;
139   
140    int sequentialPatientNumber = 0;
141    char  char_sequentialPatientNumber[10]; // 999999999 patients in a directory should be enough?
142    pa = dcmdir->GetFirstPatient(); 
143    while ( pa )
144    {  // on degouline les PATIENT du DICOMDIR
145    
146       sequentialPatientNumber++;
147       sprintf (char_sequentialPatientNumber, "%d", sequentialPatientNumber);
148       //patName = pa->GetEntryString(0x0010, 0x0010);
149       
150      
151       //codedName = "g^" + GDCM_NAME_SPACE::Util::ConvertToMD5(patName);
152       codedName = "g^Patient" + std::string(char_sequentialPatientNumber);
153       patID = pa->GetEntryString(0x0010, 0x0020);
154       codedID = GDCM_NAME_SPACE::Util::ConvertToMD5(patID);
155       
156       if (verbose) {
157          std::cout << "[" << patName << "] --> [" << codedName << "]" << std::endl;
158          std::cout << "[" << patID   << "] --> [" << codedID   << "]"  << std::endl;                 
159       } 
160       st = pa->GetFirstStudy();
161       while ( st ) 
162       { // on degouline les STUDY de ce patient
163          se = st->GetFirstSerie();
164          while ( se ) 
165          { // on degouline les SERIES de cette study
166             im = se->GetFirstImage();
167             while ( im ) 
168             { // on degouline les Images de cette serie       
169                fullFileName = dirName;
170                fullFileName +=  GDCM_NAME_SPACE::GDCM_FILESEPARATOR;
171                fullFileName += im->GetEntryString(0x0004, 0x1500);
172                if (verbose)
173                   std::cout << "FileName " << fullFileName << std::endl;
174
175                f = GDCM_NAME_SPACE::File::New( );
176                   f->SetMaxSizeLoadEntry(0x7fff);  // we want to load entries of any length !
177                   f->SetLoadMode(loadMode);
178                   f->SetFileName( fullFileName );
179                if ( !f->Load() )
180                  std::cout << "Load failed for [" << fullFileName << "]" << std::endl; 
181                else
182                   if (verbose)
183                      std::cout << "Load successed for [" << fullFileName << "]" << std::endl;
184
185                // 
186                //  Choose the fields to anonymize.
187                // 
188
189                // Institution name 
190                f->AddAnonymizeElement( 0x0008, 0x0080, "Xanadoo" );
191
192                // Patient's name 
193                f->AddAnonymizeElement( 0x0010, 0x0010, codedName ); 
194     
195                // Patient's ID
196                //f->AddAnonymizeElement( 0x0010, 0x0020,"1515" );
197                f->AddAnonymizeElement( 0x0010, 0x0020,codedID );
198                // Patient's Birthdate
199                f->AddAnonymizeElement( 0x0010, 0x0030,"11111111" );
200                // Patient's Adress
201                f->AddAnonymizeElement( 0x0010, 0x1040,"Sing-sing" );
202                // Patient's Mother's Birth Name
203                f->AddAnonymizeElement( 0x0010, 0x1060,"g^Vampirella" );
204        
205                // Study Instance UID
206                // we may not brutaly overwrite it
207                //f->AddAnonymizeElement( 0x0020, 0x000d, "9.99.999.9999" );
208    
209                // Telephone
210                f->AddAnonymizeElement(0x0010, 0x2154, "3615" );
211
212                // deal with user defined Elements set
213
214                for (int ri=0; ri<rubOutNb; ri++)
215                {
216                   f->AddAnonymizeElement((uint32_t)elemsToRubOut[2*ri], 
217                                          (uint32_t)elemsToRubOut[2*ri+1],"*" ); 
218                }
219
220    // ============================================================
221    //   Load the pixels in memory.
222    // ============================================================
223
224                // We need a gdcm::FileHelper, since we want to load the pixels        
225                GDCM_NAME_SPACE::FileHelper *fh = GDCM_NAME_SPACE::FileHelper::New(f);
226
227                // unit8_t DOESN'T mean it's mandatory for the image to be a 8 bits one !
228                // Feel free to cast if you know it's not. 
229
230                uint8_t *imageData = fh->GetImageData();
231
232                if ( imageData == 0 )
233                {
234                    std::cerr << "Sorry, Pixels of [" << fullFileName <<"]  are not "
235                              << " gdcm-readable."       << std::endl
236                              << "Use exAnonymizeNoLoad" << std::endl;
237                    f->Delete();
238                    fh->Delete();
239                    return 0;
240                }
241                
242    // ============================================================
243       
244               f->AnonymizeFile();    
245
246               f->ClearAnonymizeList();
247               f->Delete();
248  
249               im = se->GetNextImage(); 
250               f->Delete();
251               fh->Delete();                  
252            }
253            se = st->GetNextSerie();   
254         }
255         st = pa->GetNextStudy();
256      }     
257      pa = dcmdir->GetNextPatient(); 
258      
259
260    }
261
262    dcmdir->Delete();
263    
264    if (dicomdir)
265    {
266       std::cout << "DICOMDIR creation in progress ..." << std::endl;      
267       dcmdir = GDCM_NAME_SPACE::DicomDir::New( );
268       dcmdir->SetLoadMode(loadMode);
269       dcmdir->SetDirectoryName(dirName);
270       dcmdir->Load();
271       dcmdir->Write("DICOMDIR");   
272    }
273              
274    return 0;
275    
276 }