1 /*=========================================================================
4 Module: $RCSfile: AnonymizeMultiPatient.cxx,v $
6 Date: $Date: 2006/05/30 08:26:36 $
7 Version: $Revision: 1.1 $
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 =========================================================================*/
19 #include "gdcmFileHelper.h"
20 #include "gdcmCommon.h"
22 #include "gdcmDebug.h"
23 #include "gdcmDirList.h"
25 #include "gdcmDicomDir.h"
26 #include "gdcmDicomDirPatient.h"
27 #include "gdcmDicomDirStudy.h"
28 #include "gdcmDicomDirSerie.h"
29 #include "gdcmDicomDirImage.h"
31 #include "gdcmArgMgr.h"
36 int main(int argc, char *argv[])
39 " \n AnonymizeMultiPatient :\n ",
40 " AnonymizeMultiPatient a full gdcm-readable Dicom image ",
41 " Warning : the image is OVERWRITTEN ",
42 " to preserve image integrity, use a copy. ",
43 " usage: AnonymizeMultiPatient dirin=inputDirectoryName dirout=outputDirectoryName",
44 " listOfElementsToRubOut : group-elem,g2-e2,... (in hexa, no space) ",
45 " of extra Elements to rub out ",
46 " noshadowseq: user doesn't want to load Private Sequences ",
47 " noshadow : user doesn't want to load Private groups (odd number) ",
48 " noseq : user doesn't want to load Sequences ",
49 " verbose : user wants to run the program in 'verbose mode' ",
50 " debug : user wants to run the program in 'debug mode' ",
53 // ----- Initialize Arguments Manager ------
54 gdcm::ArgMgr *am = new gdcm::ArgMgr(argc, argv);
56 if (argc == 1 || am->ArgMgrDefined("usage"))
58 am->ArgMgrUsage(usage); // Display 'usage'
62 const char *dirName = am->ArgMgrGetString("dirin");
63 if ( dirName == NULL )
70 char *outputDirName = am->ArgMgrWantString("dirout",usage);
71 if ( outputDirName == NULL )
78 bool verbose = am->ArgMgrDefined("verbose");
80 if (am->ArgMgrDefined("debug"))
81 gdcm::Debug::DebugOn();
83 int loadMode = gdcm::LD_ALL;
84 if ( am->ArgMgrDefined("noshadowseq") )
85 loadMode |= gdcm::LD_NOSHADOWSEQ;
88 if ( am->ArgMgrDefined("noshadow") )
89 loadMode |= gdcm::LD_NOSHADOW;
90 if ( am->ArgMgrDefined("noseq") )
91 loadMode |= gdcm::LD_NOSEQ;
95 uint16_t *elemsToRubOut = am->ArgMgrGetXInt16Enum("rubout", &rubOutNb);
97 // if unused Param we give up
98 if ( am->ArgMgrPrintUnusedLabels() )
100 am->ArgMgrUsage(usage);
105 delete am; // we don't need Argument Manager any longer
107 // ----------------------------------------------------------
109 // ----- Begin Processing -----
111 gdcm::DicomDir *dcmdir;
113 // we ask for Directory parsing
115 dcmdir = gdcm::DicomDir::New( );
117 dcmdir->SetLoadMode(loadMode);
118 dcmdir->SetDirectoryName(dirName);
123 gdcm::DicomDirPatient *pa;
124 gdcm::DicomDirStudy *st;
125 gdcm::DicomDirSerie *se;
126 gdcm::DicomDirVisit *vs;
127 gdcm::DicomDirImage *im;
129 // Test if the DicomDir contains any Patient
130 pa = dcmdir->GetFirstPatient();
133 std::cout<<" DicomDir '"<< dirName
134 <<" has no patient"<<std::endl
135 <<" ...Failed"<<std::endl;
142 std::cout << "-------------------------- Directory [" << dirName << "] parsed" << std::endl;
144 // Since files may be help in a Directory tree-like structure
145 // we should have to duplicate this structure.
146 // No time to code that stuff
147 // --> We 'AnonymizeNoLoad' (overwrite the files)
149 // Do not remove the commented out lines.
150 // They will be usefull in a further program.
152 std::string systemCommand;
154 std::cout << "Check for output directory :[" << outputDirName << "]."
156 if ( ! gdcm::DirList::IsDirectory(outputDirName) ) // dirout not found
158 std::string strDirNameout(outputDirName); // to please gcc 4
159 systemCommand = "mkdir " +strDirNameout; // create it!
161 std::cout << systemCommand << std::endl;
162 system (systemCommand.c_str());
163 if ( ! gdcm::DirList::IsDirectory(outputDirName) ) // be sure it worked
165 std::cout << "KO : not a dir : [" << outputDirName << "] (creation failure ?)" << std::endl;
170 std::cout << "Directory [" << outputDirName << "] created." << std::endl;
175 std::cout << "Output Directory [" << outputDirName << "] already exists; Used as is." << std::endl;
180 gdcm::FileHelper *fh;
181 // std::string outputFileName;
183 std::string codedName;
188 std::cout << "Pat.Name:[" << pa->GetEntryString(0x0010, 0x0010) <<"]"; // Patient's Name
189 std::cout << " Pat.ID:[";
190 std::cout << pa->GetEntryString(0x0010, 0x0020) << "]" << std::endl; // Patient ID
192 std::string patName = pa->GetEntryString(0x0010, 0x0010);
193 //codedName = "g^" + gdcm::Util::ConvertToMD5(patName); // just to be sure MD5 is not guilty
194 std::string fullFileName;
196 std::cout << patName << " --> " << codedName << std::endl;
198 st = pa->GetFirstStudy();
200 { // on degouline les STUDY de ce patient
203 std::cout << "--- Stud.descr:[" << st->GetEntryString(0x0008, 0x1030) << "]"; // Study Description
204 std::cout << " Stud.ID:[" << st->GetEntryString(0x0020, 0x0010) << "]"; // Study ID
205 std::cout << std::endl;
207 se = st->GetFirstSerie();
209 { // on degouline les SERIES de cette study
212 std::cout << "--- --- Ser.Descr:["<< se->GetEntryString(0x0008, 0x103e) << "]"; // Series Description
213 std::cout << " Ser.nb:[" << se->GetEntryString(0x0020, 0x0011) << "]"; // Series number
214 std::cout << " Mod.:[" << se->GetEntryString(0x0008, 0x0060) << "]"; // Modality
215 std::cout << " Serie Inst.UID.:[" << se->GetEntryString(0x0020, 0x000e) << "]"; // Series Instance UID
216 std::cout << std::endl;
219 im = se->GetFirstImage();
220 std::string ReferencedFileID;
222 { // on degouline les IMAGEs de cette serie
223 ReferencedFileID = im->GetEntryString(0x0004, 0x1500);
226 std::cout << "--- --- --- "<< " IMAGE Ref. File ID :[" << ReferencedFileID
227 << "]" << std::endl; // File name (Referenced File ID)
229 f = gdcm::File::New( );
230 f->SetLoadMode(loadMode);
231 fullFileName = dirName;
233 std::cout << "fullFileName (1) " << fullFileName << std::endl;
234 std::cout << "ReferencedFileID " << ReferencedFileID << std::endl;
235 fullFileName = fullFileName + "/" + ReferencedFileID;
236 std::cout << "fullFileName (2) " << fullFileName << std::endl;
238 f->SetFileName( fullFileName );
241 std::cout << "Load failed for [" << fullFileName << "]" << std::endl;
243 std::cout << "Load successed for [" << fullFileName << "]" << std::endl;
246 // Choose the fields to anonymize.
250 f->AddAnonymizeElement( 0x0008, 0x0080, "Xanadoo" );
253 f->AddAnonymizeElement( 0x0010, 0x0010, codedName );
256 f->AddAnonymizeElement( 0x0010, 0x0020,"1515" );
257 // Patient's Birthdate
258 f->AddAnonymizeElement( 0x0010, 0x0030,"11111111" );
260 f->AddAnonymizeElement( 0x0010, 0x1040,"Sing-sing" );
261 // Patient's Mother's Birth Name
262 f->AddAnonymizeElement( 0x0010, 0x1060,"g^Vampirella" );
264 // Study Instance UID
265 // we may not brutaly overwrite it
266 //f->AddAnonymizeElement( 0x0020, 0x000d, "9.99.999.9999" );
269 f->AddAnonymizeElement(0x0010, 0x2154, "3615" );
271 // deal with user defined Elements set
273 std::cout << "rubOutNb " << rubOutNb << std::endl;
274 for (int ri=0; ri<rubOutNb; ri++)
276 f->AddAnonymizeElement((uint32_t)elemsToRubOut[2*ri],
277 (uint32_t)elemsToRubOut[2*ri+1],"*" );
280 // The gdcm::File is modified in memory
281 // f->AnonymizeFile();
284 // Overwrite the file
286 // The gdcm::File remains untouched in memory
287 f->AnonymizeNoLoad();
289 // ============================================================
291 // ============================================================
294 // No need to load the pixels in memory.
295 // File will be overwritten
297 // Do not remove the commented out lines.
298 // They will be usefull in a further program.
302 fh = gdcm::FileHelper::New(f);
304 // unit8_t DOESN'T mean it's mandatory for the image to be a 8 bits one !
305 // Feel free to cast if you know it's not.
307 uint8_t *imageData = fh->GetImageData();
309 if ( imageData == 0 )
311 std::cerr << "Sorry, Pixels of" << im->GetEntryString(0x0004, 0x1500) <<" are not "
312 << " gdcm-readable." << std::endl
313 << "Use AnonymizeNoLoad" << std::endl;
319 // Since we just Anonymized the file, we *know* no modification
320 // was performed on the pixels.
321 // The written image will not appear as a 'Secondary Captured image'
322 // nor as a DERIVED one
324 fh->SetContentType(gdcm::UNMODIFIED_PIXELS_IMAGE);
325 outputFileName = outputDirName + "/" + im->GetEntryString(0x0004, 0x1500);
326 fh->WriteDcmExplVR(outputFileName);
327 std::cout <<"End Anonymize" << std::cout;
333 f->ClearAnonymizeList();
335 im = se->GetNextImage();
337 se = st->GetNextSerie();
339 st = pa->GetNextStudy();
342 pa = dcmdir->GetNextPatient();