1 /*=========================================================================
4 Module: $RCSfile: exExtractCSA.cxx,v $
6 Date: $Date: 2007/06/21 15:06:13 $
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 =========================================================================*/
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-1010,0029-1020 ",
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"))
226 am->ArgMgrGetXInt16Enum("extract", &extractNb);
227 std::cout << "extractNb=" << extractNb << std::endl;
229 for (int k=0;k<extractNb; k++)
230 std::cout << std::hex << elemsToExtract[2*k] << "|" << elemsToExtract[2*k+1] <<std::endl;
234 elemsToExtract = new uint16_t[4];
235 elemsToExtract[0] = 0x0029;
236 elemsToExtract[1] = 0x1010;
237 elemsToExtract[2] = 0x0029;
238 elemsToExtract[3] = 0x1020;
242 /* if unused Param we give up */
243 if ( am->ArgMgrPrintUnusedLabels() )
245 am->ArgMgrUsage(usage);
249 delete am; // ------ we don't need Arguments Manager any longer ------
251 // ============================================================
252 // Read the input image.
253 // ============================================================
255 GDCM_NAME_SPACE::File *f = GDCM_NAME_SPACE::File::New( );
257 //f->SetLoadMode(GDCM_NAME_SPACE::LD_NOSEQ | GDCM_NAME_SPACE::LD_NOSHADOW);
258 f->SetFileName( fileName );
259 f->SetMaxSizeLoadEntry(0xffff);
260 bool res = f->Load();
262 if( GDCM_NAME_SPACE::Debug::GetDebugFlag())
264 std::cout << "---------------------------------------------" << std::endl;
266 std::cout << "---------------------------------------------" << std::endl;
269 std::cerr << "Sorry, " << fileName << " not a gdcm-readable "
270 << "DICOM / ACR File"
275 std::cout << " ... is readable " << std::endl;
278 // --------------------------------------------------------
282 // --------------------------------------------------------
284 // For each tag user wants to extract :
286 for (int tag_no=0; tag_no<extractNb; tag_no++) {
288 uint16_t group = elemsToExtract[2*tag_no];
289 uint16_t elem = elemsToExtract[2*tag_no+1];
292 std::cout << "Let's try tag : " << std::hex << group << "|" << elem << std::endl;
294 std::string dicom_tag_value = f->GetEntryString(group, elem);
295 if (dicom_tag_value == GDCM_NAME_SPACE::GDCM_UNFOUND)
297 GDCM_NAME_SPACE::DictEntry *dictEntry = f->GetPubDict()->GetEntry( group, elem);
298 if (dictEntry != NULL)
299 std::cerr << "Image doesn't contain any tag: " << dictEntry->GetName()
302 std::cerr << "Dicom Dictionary doesn't contain any tag: "
303 << std::hex << group << "|" << elem << std::endl;
308 GDCM_NAME_SPACE::DocEntry *dicom_tag_doc = f->GetDocEntry(group, elem);
309 GDCM_NAME_SPACE::DataEntry *dicom_tag = dynamic_cast<GDCM_NAME_SPACE::DataEntry *>(dicom_tag_doc);
312 std::cerr << "Sorry DataEntry only please" << std::endl;
317 // Write out the data as a file:
318 std::ofstream o(tempWorkFile);
321 std::cerr << "Problem opening file: [" << tempWorkFile << "]"
326 o.write((char*)dicom_tag->GetBinArea(), dicom_tag->GetLength());
330 std::ifstream is( tempWorkFile );
335 std::cout << dummy << std::endl;
336 if( strcmp( dummy, "SV10" ) )
338 std::cerr << "Either not a SV10 header or filled with 0..." << std::endl;
343 if( strcmp( dummy, "\4\3\2\1" ) )
345 std::cerr << "Either not a SV10 header or filled with 0..." << std::endl;
349 std::cout << (int)dummy[0] << (int)dummy[1] << (int)dummy[2]
350 << (int)dummy[3]<< std::endl;
352 is.read((char*)&n, sizeof(n));
354 std::cout << "number of entries " <<n << std::endl;
356 is.read((char*)&unused, sizeof(unused));
358 std::cout << "unused " << unused<< std::endl;
359 assert( unused == 77 ); // 'M' character...
361 for(uint32_t i = 0; i < n; ++i)
364 std::cout << "============================================== " << i <<
367 name[64] = 0; // security
368 //std::cout << "Pos 0x" << std::hex << is.tellg() << std::dec << std::endl;
371 std::cout << "Name=[" << name << "]" << std::endl;
373 is.read((char*)&vm, sizeof(vm));
375 std::cout << "vm=" << vm << std::endl;
378 assert( vr[2] == vr[3] && vr[2] == 0 );
380 std::cout << "vr=[" << vr << "]" <<std::endl;
382 is.read((char*)&syngodt, sizeof(syngodt));
383 check_mapping(syngodt, vr);
386 std::cout << "syngodt=" << syngodt << std::endl;
388 is.read((char*)&nitems, sizeof(nitems));
390 std::cout << "nitems=" << nitems<< std::endl;
392 is.read((char*)&xx, sizeof(xx));
393 //std::cout << "xx=" << xx<< std::endl;
394 assert( xx == 77 || xx == 205 );
396 myEntry = new CSA_entry;
397 myEntry->Name = name;
400 myEntry->Syngodt = syngodt;
401 myEntry->Nitems = nitems;
403 for( uint32_t j = 0; j < nitems; ++j)
406 std::cout << "-------------------------------------------- " << j
409 is.read((char*)&item_xx, 4*sizeof(uint32_t));
411 std::cout << std::dec
412 << "item_xx=" << item_xx[0] << " " << item_xx[1] << " "
413 << item_xx[2] << " " << item_xx[3] << std::endl;
414 //std::cout << "0x" << std::hex << is.tellg() << std::dec << std::endl;
415 assert( item_xx[2] == 77 || item_xx[2] == 205 );
416 uint32_t len = item_xx[1]; // 2nd element
418 std::cout << "len=" << len << std::endl;
419 assert( item_xx[0] == item_xx[1] && item_xx[1] == item_xx[3] );
420 char *val = new char[len+1];
421 val[len] = 0; // security
423 // WARNING vr does not means anything AFAIK,
424 // simply print the value as if it was IS/DS or LO (ASCII)
426 std::cout << "val=[" << val << "]" << std::endl;
429 uint32_t dummy_len = (4 - len % 4) % 4;
430 is.read(dummy, dummy_len );
433 for(uint32_t d= 0; d < dummy_len; ++d)
435 // I think dummy should always be 0
439 std::cout << "dummy=" << (int)dummy[d] << std::endl;
443 myItem = new CSA_item;
444 for (int i2=0; i2<4; i2++)
445 myItem->Item_xx[i2] = item_xx[i2];
449 myEntry->Items_set.push_back(myItem);
453 myMap[name] = myEntry;
456 std::cout << "================================================================"
458 << "=== Extract :" << std::hex << group << " " << elem << "========"
460 << "================================================================"
463 PrintCSA_content (myMap);
464 DeleteCSA_content (myMap);