1 /*=========================================================================
4 Module: $RCSfile: exExtractCSA.cxx,v $
6 Date: $Date: 2007/06/07 16:13:14 $
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 =========================================================================*/
20 * http://www.enac.northwestern.edu/~tew/archives/2003/02/25/incomplete-dicom-headers/
21 * http://www.nmr.mgh.harvard.edu/~rudolph/software/vox2ras/download/vox2ras_rsolve.m
22 * http://www.mail-archive.com/freesurfer@nmr.mgh.harvard.edu/msg03409.html
23 * http://www.mmrrcc.upenn.edu/CAMRIS/cfn/dicomhdr.html
27 // http://www.mmrrcc.upenn.edu/CAMRIS/cfn/dicomhdr.html
37 #include "gdcmFileHelper.h"
38 #include "gdcmCommon.h"
39 #include "gdcmDebug.h"
40 #include "gdcmDocEntry.h"
41 #include "gdcmDataEntry.h"
42 #include "gdcmSeqEntry.h"
43 #include "gdcmSQItem.h"
44 #include "gdcmArgMgr.h"
46 // Looks like there is mapping in between syngodt and vr...
60 // --------------------------------------------------------
68 typedef std::vector<CSA_item *> ItemVector;
79 typedef std::map<std::string, CSA_entry *> CSA_content;
81 // --------------------------------------------------------
90 static equ mapping[] = {
106 bool check_mapping(uint32_t syngodt, const char *vr)
108 static const unsigned int max = sizeof(mapping) / sizeof(equ);
110 const equ *p = mapping;
111 assert( syngodt <= mapping[max-1].syngodt );
112 while(p->syngodt < syngodt )
114 //std::cout << "mapping:" << p->vr << std::endl;
117 assert( p->syngodt == syngodt ); // or else need to update mapping
118 const char* lvr = p->vr;
119 int check = strcmp(vr, lvr) == 0;
125 ///\to fix the Desctructor!
126 void DeleteCSA_content (CSA_content &myMap) {
127 for ( CSA_content::const_iterator it = myMap.begin();
131 ItemVector item_v = (*it).second->Items_set;
132 for ( ItemVector::const_iterator it2 = item_v.begin();
138 //delete (*it).second;
142 void PrintCSA_content(CSA_content &myMap) {
144 for ( CSA_content::const_iterator it = myMap.begin();
148 std::cout << "[" << (*it).second->Name << "] : VR=[" << (*it).second->VR
149 << "] vm = " << (*it).second->VM << std::endl;
151 ItemVector item_v = (*it).second->Items_set;
152 for ( ItemVector::const_iterator it2 = item_v.begin();
156 std::cout << " --- item no : " << item_no << std::endl;
157 std::cout << " Item_xxx : " << (*it2)->Item_xx[0] << " "
158 << (*it2)->Item_xx[1]
159 << " " << (*it2)->Item_xx[2] << " " << (*it2)->Item_xx[3]
162 std::cout << " Len = " << (*it2)->Len ;
163 std::cout << " Value = [" << (*it2)->Value << "]" << std::endl;
170 int main(int argc, char *argv[])
173 "\n exExtractCSA :\n ",
174 "Extracts and displays the CSA tag(s) of gdcm-parsable Dicom file ",
176 "usage: exExtractCSA {filein=inputFileName|dirin=inputDirectoryName} ",
177 " tmp=temporaryWorkFileName ",
178 " [extract=listOfElementsToExtract] ",
179 " [ { [noshadowseq] | [noshadow][noseq] } ] [debug] ",
180 " inputFileName : Name of the (single) file user wants to anonymize ",
181 " listOfElementsExtract : group-elem,g2-e2,... (in hexa, no space) ",
182 " of Elements to extract ",
183 " default : 0029-1210,0029-1220 ",
184 " noshadowseq: user doesn't want to load Private Sequences ",
185 " noshadow : user doesn't want to load Private groups (odd number) ",
186 " noseq : user doesn't want to load Sequences ",
187 " verbose : developper wants to run the program in 'verbose mode' ",
188 " debug : developper wants to run the program in 'debug mode' ",
191 // ----- Initialize Arguments Manager ------
193 GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
195 if (am->ArgMgrDefined("usage") || argc == 1)
197 am->ArgMgrUsage(usage); // Display 'usage'
202 if (am->ArgMgrDefined("debug"))
203 GDCM_NAME_SPACE::Debug::DebugOn();
205 bool verbose = am->ArgMgrDefined("verbose");
207 const char *fileName = am->ArgMgrGetString("filein");
209 int loadMode = GDCM_NAME_SPACE::LD_ALL;
210 if ( am->ArgMgrDefined("noshadowseq") )
211 loadMode |= GDCM_NAME_SPACE::LD_NOSHADOWSEQ;
214 if ( am->ArgMgrDefined("noshadow") )
215 loadMode |= GDCM_NAME_SPACE::LD_NOSHADOW;
216 if ( am->ArgMgrDefined("noseq") )
217 loadMode |= GDCM_NAME_SPACE::LD_NOSEQ;
220 const char *tempWorkFile = am->ArgMgrGetString("tmp");
223 uint16_t *elemsToExtract;
224 if (am->ArgMgrDefined("extract"))
225 am->ArgMgrGetXInt16Enum("extract", &extractNb);
228 elemsToExtract = new uint16_t[4];
229 elemsToExtract[0] = 0x0029;
230 elemsToExtract[1] = 0x1210;
231 elemsToExtract[2] = 0x0029;
232 elemsToExtract[3] = 0x1220;
236 /* if unused Param we give up */
237 if ( am->ArgMgrPrintUnusedLabels() )
239 am->ArgMgrUsage(usage);
243 delete am; // ------ we don't need Arguments Manager any longer ------
245 // ============================================================
246 // Read the input image.
247 // ============================================================
249 gdcm::File *f = gdcm::File::New( );
251 //f->SetLoadMode(gdcm::LD_NOSEQ | gdcm::LD_NOSHADOW);
252 f->SetFileName( fileName );
253 f->SetMaxSizeLoadEntry(0xffff);
254 bool res = f->Load();
256 if( gdcm::Debug::GetDebugFlag())
258 std::cout << "---------------------------------------------" << std::endl;
260 std::cout << "---------------------------------------------" << std::endl;
263 std::cerr << "Sorry, " << fileName << " not a gdcm-readable "
264 << "DICOM / ACR File"
269 std::cout << " ... is readable " << std::endl;
272 // --------------------------------------------------------
276 // --------------------------------------------------------
278 // For each tag user wants to extract :
280 for (int tag_no=0; tag_no<extractNb; tag_no++) {
282 uint16_t group = elemsToExtract[2*tag_no];
283 uint16_t elem = elemsToExtract[2*tag_no+1];
285 std::string dicom_tag_value = f->GetEntryString(group, elem);
286 if (dicom_tag_value == gdcm::GDCM_UNFOUND)
288 gdcm::DictEntry *dictEntry = f->GetPubDict()->GetEntry( group, elem);
289 std::cerr << "Image doesn't contain any tag: " << dictEntry->GetName()
295 gdcm::DocEntry *dicom_tag_doc = f->GetDocEntry(group, elem);
296 gdcm::DataEntry *dicom_tag = dynamic_cast<gdcm::DataEntry *>(dicom_tag_doc);
299 std::cerr << "Sorry DataEntry only please" << std::endl;
304 // Write out the data as a file:
305 std::ofstream o(tempWorkFile);
308 std::cerr << "Problem opening file: [" << tempWorkFile << "]"
313 o.write((char*)dicom_tag->GetBinArea(), dicom_tag->GetLength());
317 std::ifstream is( tempWorkFile );
322 std::cout << dummy << std::endl;
323 if( strcmp( dummy, "SV10" ) )
325 std::cerr << "Either not a SV10 header or filled with 0..." << std::endl;
330 if( strcmp( dummy, "\4\3\2\1" ) )
332 std::cerr << "Either not a SV10 header or filled with 0..." << std::endl;
336 std::cout << (int)dummy[0] << (int)dummy[1] << (int)dummy[2]
337 << (int)dummy[3]<< std::endl;
339 is.read((char*)&n, sizeof(n));
341 std::cout << "number of entries " <<n << std::endl;
343 is.read((char*)&unused, sizeof(unused));
345 std::cout << "unused " << unused<< std::endl;
346 assert( unused == 77 ); // 'M' character...
348 for(uint32_t i = 0; i < n; ++i)
351 std::cout << "============================================== " << i <<
354 name[64] = 0; // security
355 //std::cout << "Pos 0x" << std::hex << is.tellg() << std::dec << std::endl;
358 std::cout << "Name=[" << name << "]" << std::endl;
360 is.read((char*)&vm, sizeof(vm));
362 std::cout << "vm=" << vm << std::endl;
365 assert( vr[2] == vr[3] && vr[2] == 0 );
367 std::cout << "vr=[" << vr << "]" <<std::endl;
369 is.read((char*)&syngodt, sizeof(syngodt));
370 check_mapping(syngodt, vr);
373 std::cout << "syngodt=" << syngodt << std::endl;
375 is.read((char*)&nitems, sizeof(nitems));
377 std::cout << "nitems=" << nitems<< std::endl;
379 is.read((char*)&xx, sizeof(xx));
380 //std::cout << "xx=" << xx<< std::endl;
381 assert( xx == 77 || xx == 205 );
383 myEntry = new CSA_entry;
384 myEntry->Name = name;
387 myEntry->Syngodt = syngodt;
388 myEntry->Nitems = nitems;
390 for( uint32_t j = 0; j < nitems; ++j)
393 std::cout << "-------------------------------------------- " << j
396 is.read((char*)&item_xx, 4*sizeof(uint32_t));
398 std::cout << "item_xx=" << item_xx[0] << " " << item_xx[1] << " "
399 << item_xx[2] << " " << item_xx[3] << std::endl;
400 //std::cout << "0x" << std::hex << is.tellg() << std::dec << std::endl;
401 assert( item_xx[2] == 77 || item_xx[2] == 205 );
402 uint32_t len = item_xx[1]; // 2nd element
404 std::cout << "len=" << len << std::endl;
405 assert( item_xx[0] == item_xx[1] && item_xx[1] == item_xx[3] );
406 char *val = new char[len+1];
407 val[len] = 0; // security
409 // WARNING vr does not means anything AFAIK,
410 // simply print the value as if it was IS/DS or LO (ASCII)
412 std::cout << "val=[" << val << "]" << std::endl;
415 uint32_t dummy_len = (4 - len % 4) % 4;
416 is.read(dummy, dummy_len );
419 for(uint32_t d= 0; d < dummy_len; ++d)
421 // I think dummy should always be 0
425 std::cout << "dummy=" << (int)dummy[d] << std::endl;
429 myItem = new CSA_item;
430 for (int i2=0; i2<4; i2++)
431 myItem->Item_xx[i2] = item_xx[i2];
435 myEntry->Items_set.push_back(myItem);
439 myMap[name] = myEntry;
442 std::cout << "================================================================"
444 << "=== Extract :" << std::hex << group << " " << elem << "========"
446 << "================================================================"
449 PrintCSA_content (myMap);
450 DeleteCSA_content (myMap);