1 /*=========================================================================
4 Module: $RCSfile: AnonymizeReWriteMultiPatient.cxx,v $
6 Date: $Date: 2008/03/18 13:37:54 $
7 Version: $Revision: 1.4 $
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.
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.
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"
29 #include "gdcmFileHelper.h"
31 #include "gdcmArgMgr.h"
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.
42 int main(int argc, char *argv[])
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 " dirin : directory holding images to anonymize ",
52 " rootname : root for the 'anonymized' name ",
53 " listOfElementsToRubOut : group-elem,g2-e2,... (in hexa, no space) ",
54 " of extra Elements to rub out ",
55 " dicomdir : user wants to generate a DICOMDIR ",
56 " verbose : user wants to run the program in 'verbose mode' ",
57 " debug : user wants to run the program in 'debug mode' ",
62 // ----- Initialize Arguments Manager ------
63 GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
65 if (argc == 1 || am->ArgMgrDefined("usage"))
67 am->ArgMgrUsage(usage); // Display 'usage'
71 const char * name = am->ArgMgrGetString("dirin");
78 std::string dirName = name;
80 bool verbose = ( 0 != am->ArgMgrDefined("verbose") );
81 bool dicomdir = ( 0 != am->ArgMgrDefined("dicomdir") );
83 const char *rootname = am->ArgMgrGetString("rootname","Patient");
85 if (am->ArgMgrDefined("debug"))
86 GDCM_NAME_SPACE::Debug::DebugOn();
88 int loadMode = GDCM_NAME_SPACE::LD_ALL;
91 uint16_t *elemsToRubOut = am->ArgMgrGetXInt16Enum("rubout", &rubOutNb);
93 // ----------- if unused Param we give up
94 if ( am->ArgMgrPrintUnusedLabels() )
96 am->ArgMgrUsage(usage);
101 delete am; // we don't need Argument Manager any longer
104 // ----------------------------------------------------------
107 // ----- Begin Processing -----
109 GDCM_NAME_SPACE::DicomDir *dcmdir;
111 // we ask for Directory parsing
113 dcmdir = GDCM_NAME_SPACE::DicomDir::New( );
114 dcmdir->SetLoadMode(loadMode);
115 dcmdir->SetDirectoryName(dirName);
119 std::cout << "======================= End Parsing Directory" << std::endl;
121 // ----- Check the result
123 if ( !dcmdir->GetFirstPatient() )
125 std::cout << "No patient found (?!?). Exiting."
131 GDCM_NAME_SPACE::DicomDirPatient *pa;
132 GDCM_NAME_SPACE::DicomDirStudy *st;
133 GDCM_NAME_SPACE::DicomDirSerie *se;
134 GDCM_NAME_SPACE::DicomDirImage *im;
136 std::string codedName;
138 std::string fullFileName;
142 GDCM_NAME_SPACE::File *f;
145 //GDCM_NAME_SPACE::Debug::DebugOn();
148 int sequentialPatientNumber = 0;
149 char char_sequentialPatientNumber[10]; // 999999999 patients in a directory should be enough?
150 pa = dcmdir->GetFirstPatient();
152 { // on degouline les PATIENT du DICOMDIR
154 sequentialPatientNumber++;
155 sprintf (char_sequentialPatientNumber, "%d", sequentialPatientNumber);
156 //patName = pa->GetEntryString(0x0010, 0x0010);
159 //codedName = "g^" + GDCM_NAME_SPACE::Util::ConvertToMD5(patName);
160 codedName = "g^" + std::string(rootname) + std::string(char_sequentialPatientNumber);
161 patID = pa->GetEntryString(0x0010, 0x0020);
162 codedID = GDCM_NAME_SPACE::Util::ConvertToMD5(patID);
165 std::cout << "[" << patName << "] --> [" << codedName << "]" << std::endl;
166 std::cout << "[" << patID << "] --> [" << codedID << "]" << std::endl;
168 st = pa->GetFirstStudy();
170 { // on degouline les STUDY de ce patient
171 se = st->GetFirstSerie();
173 { // on degouline les SERIES de cette study
174 im = se->GetFirstImage();
176 { // on degouline les Images de cette serie
177 fullFileName = dirName;
178 const char lastChar = dirName.c_str()[strlen(dirName.c_str())-1];
179 if ( lastChar != '/' && lastChar != '\\')
180 fullFileName += GDCM_NAME_SPACE::GDCM_FILESEPARATOR;
181 fullFileName += im->GetEntryString(0x0004, 0x1500);
183 // -- remove trailing space, if any
184 int pos=fullFileName.length()-1;
185 if (fullFileName[pos] == ' ')
187 fullFileName.erase(pos);
192 std::cout << "FileName [" << fullFileName << "]" << std::endl;
194 f = GDCM_NAME_SPACE::File::New( );
195 f->SetMaxSizeLoadEntry(0x7fff); // we want to load entries of any length !
196 f->SetLoadMode(loadMode);
197 f->SetFileName( fullFileName );
200 std::cout << "Load failed for [" << fullFileName << "]" << std::endl;
202 //continue; // or return 0; ?
207 std::cout << "Load successed for [" << fullFileName << "]" << std::endl;
210 // Choose the fields to anonymize.
214 f->AddAnonymizeElement( 0x0008, 0x0080, "Xanadoo" );
217 f->AddAnonymizeElement( 0x0010, 0x0010, codedName );
220 //f->AddAnonymizeElement( 0x0010, 0x0020,"1515" );
221 f->AddAnonymizeElement( 0x0010, 0x0020,codedID );
222 // Patient's Birthdate
223 f->AddAnonymizeElement( 0x0010, 0x0030,"11111111" );
225 f->AddAnonymizeElement( 0x0010, 0x1040,"Sing-sing" );
226 // Patient's Mother's Birth Name
227 f->AddAnonymizeElement( 0x0010, 0x1060,"g^Vampirella" );
229 // Study Instance UID
230 // we may not brutaly overwrite it
231 //f->AddAnonymizeElement( 0x0020, 0x000d, "9.99.999.9999" );
234 f->AddAnonymizeElement(0x0010, 0x2154, "3615" );
236 // deal with user defined Elements set
238 for (int ri=0; ri<rubOutNb; ri++)
240 f->AddAnonymizeElement((uint32_t)elemsToRubOut[2*ri],
241 (uint32_t)elemsToRubOut[2*ri+1],"*" );
244 // ============================================================
245 // Load the pixels in memory.
246 // ============================================================
248 // We need a gdcm::FileHelper, since we want to load the pixels
249 GDCM_NAME_SPACE::FileHelper *fh = GDCM_NAME_SPACE::FileHelper::New(f);
251 // unit8_t DOESN'T mean it's mandatory for the image to be a 8 bits one !
252 // Feel free to cast if you know it's not.
254 uint8_t *imageData = fh->GetImageData();
256 if ( imageData == 0 )
258 std::cerr << "Sorry, Pixels of [" << fullFileName <<"] are not "
259 << " gdcm-readable." << std::endl
260 << "Use exAnonymizeNoLoad" << std::endl;
266 // ============================================================
268 f->ClearAnonymizeList();
270 fh->SetContentType(GDCM_NAME_SPACE::UNMODIFIED_PIXELS_IMAGE);
271 fh->Write(fullFileName); // WARNING : overwrites the file!
273 im = se->GetNextImage();
277 se = st->GetNextSerie();
279 st = pa->GetNextStudy();
281 pa = dcmdir->GetNextPatient();
288 std::cout << "DICOMDIR creation in progress ..." << std::endl;
289 dcmdir = GDCM_NAME_SPACE::DicomDir::New( );
290 dcmdir->SetLoadMode(loadMode);
291 dcmdir->SetDirectoryName(dirName);
293 dcmdir->Write("DICOMDIR");