]> Creatis software - gdcm.git/blob - Example/AnonymizeDicomDir.cxx
Add an executable (not yet fully checked) to anonymize a DICOMDIR
[gdcm.git] / Example / AnonymizeDicomDir.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: AnonymizeDicomDir.cxx,v $
5   Language:  C++
6   Date:      $Date: 2005/03/09 19:15:04 $
7   Version:   $Revision: 1.1 $
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 "gdcmValEntry.h"
26
27 #include "gdcmDocument.h"
28 #include "gdcmFile.h"
29
30 #include <iostream>
31
32 void AnoNoLoad(gdcm::SQItem *s, std::fstream *fp, 
33                uint16_t group, uint16_t elem, 
34                std::string val);
35
36 void AnoNoLoad(gdcm::SQItem *s, std::fstream *fp, 
37                uint16_t group, uint16_t elem, 
38                std::string val)
39 {
40    gdcm::DocEntry *d;
41    uint32_t offset;
42    uint32_t lgth;
43    uint32_t valLgth = 0;
44    std::string *spaces;
45    std::string v;
46
47    d = s->GetDocEntry( group, elem);
48
49    if ( d == NULL)
50       return;
51
52    if ( ! dynamic_cast<gdcm::ValEntry *>(d) )
53       return;
54
55    offset = d->GetOffset();
56    lgth =   d->GetLength();
57    if (valLgth < lgth)
58    {
59       spaces = new std::string( lgth-valLgth, ' ');
60       v = val + *spaces;
61       delete spaces;
62    }
63    fp->seekp( offset, std::ios::beg );
64    fp->write( v.c_str(), lgth );
65 }
66
67 int main(int argc, char *argv[])
68 {  
69    gdcm::File *f1;
70  
71    gdcm::Debug::DebugOn();
72    std::cout << "------------------------------------------------" << std::endl;
73    std::cout << "Anonymize a gdcm-readable DICOMDIR   "            << std::endl;
74    std::cout << "even some Objects are not yet taken into account" << std::endl;
75    std::cout << "Warning : the DICOMDIR is overwritten"            << std::endl;
76    std::cout << "        : to preserve file integrity "
77              << " think unto using a copy .. "                     << std::endl;
78  
79    if( argc < 3 )
80     {
81     std::cerr << "Usage " << argv[0] << " DICOMDIR to anonymize  " 
82               << std::endl;
83     return 1;
84     }
85
86    std::string fileName       = argv[1];
87
88 // ============================================================
89 //   Read the input DICOMDIR
90 // ============================================================
91
92    std::cout << argv[1] << std::endl;
93
94    f1 = new gdcm::File( fileName );
95    if (!f1->IsReadable()) {
96        std::cerr << "Sorry, " << fileName <<"  not a gdcm-readable "
97                  << "file" <<std::endl;
98    }
99    std::cout << " ... is readable " << std::endl;
100
101
102    // Directory record sequence
103    gdcm::DocEntry *e = f1->GetDocEntry(0x0004, 0x1220);
104    if ( !e )
105    {
106       std::cout << "No Directory Record Sequence (0004,1220) found" <<std::endl;;
107       return 0;         
108    }
109    
110    gdcm::SeqEntry *s = dynamic_cast<gdcm::SeqEntry *>(e);
111    if ( !s )
112    {
113       std::cout << "Element (0004,1220) is not a Sequence ?!?" <<std::endl;
114       return 0;
115    }
116
117    // Open the file LTTG (aka ALAP)
118    std::fstream *fp = new std::fstream(fileName.c_str(), 
119                               std::ios::in | std::ios::out | std::ios::binary);
120    gdcm::DocEntry *d;
121    std::string v;
122
123    int patientNumber = 0;
124    std::ostringstream oss;
125
126    gdcm::SQItem *tmpSI=s->GetFirstSQItem();  // For all the SQItems
127    while(tmpSI)
128    {
129       d = tmpSI->GetDocEntry(0x0004, 0x1430); // Directory Record Type
130       if ( gdcm::ValEntry* valEntry = dynamic_cast<gdcm::ValEntry *>(d) )
131       {
132          v = valEntry->GetValue();
133       }
134       else
135       {
136          std::cout << "(0004,1430) not a ValEntry ?!?" << std::endl;
137          continue;
138       }
139
140       if( v != "PATIENT " )
141       {
142          continue;          // Work only on PATIENT
143       }
144
145       oss << patientNumber;      
146
147       //   Overwrite the sensitive Entries
148
149       // Patient's Name
150       AnoNoLoad(tmpSI, fp, 0x0010, 0x0010, oss.str());
151       // Patient's ID
152       AnoNoLoad(tmpSI, fp, 0x0010, 0x0020, oss.str());
153       // Patient's Birth Date
154       AnoNoLoad(tmpSI, fp, 0x0010, 0x0030, oss.str());
155      // Telephone
156       AnoNoLoad(tmpSI, fp, 0x0010, 0x2154, oss.str()); 
157
158     // Aware use will add more Entries he wants to rubb out here
159
160       oss << "";
161       patientNumber++;
162       tmpSI=s->GetNextSQItem();
163    }
164
165    // Close the file ASAP
166
167    fp->close();
168    delete fp;
169     
170    delete f1;
171    return 0;
172 }
173