]> Creatis software - gdcm.git/blob - Example/AnonymizeDicomDir.cxx
ENH: fix link + update info
[gdcm.git] / Example / AnonymizeDicomDir.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: AnonymizeDicomDir.cxx,v $
5   Language:  C++
6   Date:      $Date: 2007/11/08 10:40:39 $
7   Version:   $Revision: 1.12 $
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 "gdcmGlobal.h"
19 #include "gdcmCommon.h"
20 #include "gdcmDebug.h"
21 #include "gdcmUtil.h"
22
23 #include "gdcmSQItem.h"
24 #include "gdcmSeqEntry.h"
25 #include "gdcmDataEntry.h"
26
27 #include "gdcmDocument.h"
28 #include "gdcmFile.h"
29
30 #include "gdcmArgMgr.h"
31
32 #include <iostream>
33
34 /**
35  * \brief AnonymizeDicomDir
36  */
37
38 void AnoNoLoad(GDCM_NAME_SPACE::SQItem *s, std::fstream *fp, 
39                uint16_t group, uint16_t elem, 
40                std::string val);
41
42 void AnoNoLoad(GDCM_NAME_SPACE::SQItem *s, std::fstream *fp, 
43                uint16_t group, uint16_t elem, 
44                std::string val)
45 {
46    GDCM_NAME_SPACE::DocEntry *d;
47    uint32_t offset;
48    uint32_t lgth;
49    uint32_t valLgth = 0;
50    std::string *spaces;
51    std::string v;
52
53    d = s->GetDocEntry( group, elem);
54
55    if ( d == NULL)
56       return;
57
58    if ( ! dynamic_cast<GDCM_NAME_SPACE::DataEntry *>(d) )
59       return;
60
61    offset = d->GetOffset();
62    lgth =   d->GetLength();
63    if (valLgth < lgth)
64    {
65       spaces = new std::string( lgth-valLgth, ' ');
66       v = val + *spaces;
67       delete spaces;
68    }
69    fp->seekp( offset, std::ios::beg );
70    fp->write( v.c_str(), lgth );
71 }
72
73
74 int main(int argc, char *argv[])
75
76
77    START_USAGE(usage)
78    " \n AnonymizeDicomDir :\n                                              ",
79    " Anonymize a gdcm-readable DICOMDIR                                    ",
80    "           even when some 'Objects' are not yet taken into account     ",
81    "           Warning : the DICOMDIR is overwritten                       ",
82    " usage: AnonymizeDicomDir filein=dicomDirName [debug]                  ",
83    "        debug    : developper wants to run the program in 'debug mode' ",
84    FINISH_USAGE
85
86    // ----- Initialize Arguments Manager ------   
87    GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
88   
89    if (argc == 1 || am->ArgMgrDefined("usage")) 
90    {
91       am->ArgMgrUsage(usage); // Display 'usage'
92       delete am;
93       return 0;
94    }
95  
96    char *fileName  = am->ArgMgrWantString("filein",usage); 
97
98    // if unused Param we give up
99    if ( am->ArgMgrPrintUnusedLabels() )
100    { 
101       am->ArgMgrUsage(usage);
102       delete am;
103       return 0;
104    }
105    delete am;  // --- we don't need Argument Manager any longer ---
106
107
108    //   Read the input DICOMDIR
109    GDCM_NAME_SPACE::File *f;
110    f = GDCM_NAME_SPACE::File::New( );
111    f->SetLoadMode(0);
112    f->SetFileName( fileName );
113    bool res = f->Load();  
114    if ( !res )
115    {
116        std::cerr << "Sorry, " << fileName <<"  not a gdcm-readable "
117                  << "file" <<std::endl;
118    }
119    std::cout << " ... is readable " << std::endl;
120
121    // Look for Directory record sequence
122    GDCM_NAME_SPACE::DocEntry *e = f->GetDocEntry(0x0004, 0x1220);
123    if ( !e )
124    {
125       std::cout << "No Directory Record Sequence (0004,1220) found" <<std::endl;;
126       f->Delete();
127       return 0;
128    }
129    
130    GDCM_NAME_SPACE::SeqEntry *s = dynamic_cast<GDCM_NAME_SPACE::SeqEntry *>(e);
131    if ( !s )
132    {
133       std::cout << "Element (0004,1220) is not a Sequence ?!?" <<std::endl;
134       f->Delete();
135       return 0;
136    }
137
138    // Open the file LTTG (aka ALAP)
139    std::fstream *fp = new std::fstream(fileName, 
140                               std::ios::in | std::ios::out | std::ios::binary);
141    GDCM_NAME_SPACE::DocEntry *d;
142    std::string v;
143
144    int patientNumber = 0;
145
146    std::ostringstream oss;
147
148    GDCM_NAME_SPACE::SQItem *tmpSI=s->GetFirstSQItem();  // For all the SQItems
149    while(tmpSI)
150    {
151       d = tmpSI->GetDocEntry(0x0004, 0x1430); // Directory Record Type
152       if ( GDCM_NAME_SPACE::DataEntry *dataEntry =
153       dynamic_cast<GDCM_NAME_SPACE::DataEntry *>(d) )
154       {
155          v = dataEntry->GetString();
156       }
157       else
158       {
159          std::cout << "(0004,1430) not a DataEntry ?!?" << std::endl;
160          continue;
161       }
162
163       if( v != "PATIENT " )  // Work only on PATIENT
164       {
165          tmpSI=s->GetNextSQItem();
166          continue;
167       }
168
169       oss << "P^" << patientNumber;      
170
171       //   Overwrite the sensitive Entries
172
173       // Patient's Name
174       AnoNoLoad(tmpSI, fp, 0x0010, 0x0010, oss.str());
175       // Patient's ID
176       AnoNoLoad(tmpSI, fp, 0x0010, 0x0020, oss.str());
177       // Patient's Birth Date
178       AnoNoLoad(tmpSI, fp, 0x0010, 0x0030, "11111111");
179      // Telephone
180       AnoNoLoad(tmpSI, fp, 0x0010, 0x2154, oss.str()); 
181
182       // Aware use will add here more Entries if he wants to rubb them out
183
184       oss << "";
185       patientNumber++;
186       tmpSI=s->GetNextSQItem();
187    }
188
189    // Close the file ASAP
190
191    fp->close();
192
193    delete fp;
194    f->Delete();
195    return 0;
196 }
197