1 /*=========================================================================
4 Module: $RCSfile: exExtractCSA.cxx,v $
6 Date: $Date: 2007/10/03 09:14:55 $
7 Version: $Revision: 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.
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"
47 // --------------------------------------------------------
55 typedef std::vector<CSA_item *> ItemVector;
66 typedef std::map<std::string, CSA_entry *> CSA_content;
68 // --------------------------------------------------------
77 // Looks like there is mapping in between syngodt and vr...
90 static equ mapping[] = {
109 bool check_mapping(uint32_t syngodt, const char *vr)
111 static const unsigned int max = sizeof(mapping) / sizeof(equ);
113 const equ *p = mapping;
114 assert( syngodt <= mapping[max-1].syngodt );
115 while(p->syngodt < syngodt )
117 //std::cout << "mapping:" << p->vr << std::endl;
120 assert( p->syngodt == syngodt ); // or else need to update mapping
121 const char* lvr = p->vr;
122 int check = strcmp(vr, lvr) == 0;
128 ///\to fix the Destructor!
129 void DeleteCSA_content (CSA_content &myMap) {
130 for ( CSA_content::const_iterator it = myMap.begin();
134 ItemVector item_v = (*it).second->Items_set;
135 for ( ItemVector::const_iterator it2 = item_v.begin();
141 //delete (*it).second;
145 void PrintCSA_content(CSA_content &myMap) {
147 for ( CSA_content::const_iterator it = myMap.begin();
151 std::cout << "[" << (*it).second->Name << "] : VR=[" << (*it).second->VR
152 << "] vm = " << (*it).second->VM << std::endl;
154 ItemVector item_v = (*it).second->Items_set;
155 for ( ItemVector::const_iterator it2 = item_v.begin();
159 std::cout << " --- item no : " << item_no << std::endl;
160 std::cout << " Item_xxx : " << (*it2)->Item_xx[0] << " "
161 << (*it2)->Item_xx[1]
162 << " " << (*it2)->Item_xx[2] << " " << (*it2)->Item_xx[3]
165 std::cout << " Len = " << (*it2)->Len ;
166 std::cout << " Value = [" << (*it2)->Value << "]" << std::endl;
173 int main(int argc, char *argv[])
176 "\n exExtractCSA :\n ",
177 "Extracts and displays the CSA tag(s) of gdcm-parsable Dicom file ",
179 "usage: exExtractCSA {filein=inputFileName|dirin=inputDirectoryName} ",
180 " tmp=temporaryWorkFileName ",
181 " [extract=listOfElementsToExtract] ",
182 " [ { [noshadowseq] | [noshadow][noseq] } ] [debug] ",
183 " inputFileName : Name of the (single) file user wants to anonymize ",
184 " listOfElementsExtract : group-elem,g2-e2,... (in hexa, no space) ",
185 " of Elements to extract ",
186 " default : 0029-1010,0029-1020 ",
187 " noshadowseq: user doesn't want to load Private Sequences ",
188 " noshadow : user doesn't want to load Private groups (odd number) ",
189 " noseq : user doesn't want to load Sequences ",
190 " verbose : developper wants to run the program in 'verbose mode' ",
191 " debug : developper wants to run the program in 'debug mode' ",
194 // ----- Initialize Arguments Manager ------
196 GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
198 if (am->ArgMgrDefined("usage") || argc == 1)
200 am->ArgMgrUsage(usage); // Display 'usage'
205 if (am->ArgMgrDefined("debug"))
206 GDCM_NAME_SPACE::Debug::DebugOn();
208 bool verbose = am->ArgMgrDefined("verbose");
210 const char *fileName = am->ArgMgrGetString("filein");
212 int loadMode = GDCM_NAME_SPACE::LD_ALL;
213 if ( am->ArgMgrDefined("noshadowseq") )
214 loadMode |= GDCM_NAME_SPACE::LD_NOSHADOWSEQ;
217 if ( am->ArgMgrDefined("noshadow") )
218 loadMode |= GDCM_NAME_SPACE::LD_NOSHADOW;
219 if ( am->ArgMgrDefined("noseq") )
220 loadMode |= GDCM_NAME_SPACE::LD_NOSEQ;
223 const char *tempWorkFile = am->ArgMgrGetString("tmp");
226 uint16_t *elemsToExtract;
227 if (am->ArgMgrDefined("extract"))
229 am->ArgMgrGetXInt16Enum("extract", &extractNb);
230 std::cout << "extractNb=" << extractNb << std::endl;
232 for (int k=0;k<extractNb; k++)
233 std::cout << std::hex << elemsToExtract[2*k] << "|" << elemsToExtract[2*k+1] <<std::endl;
237 elemsToExtract = new uint16_t[4];
238 elemsToExtract[0] = 0x0029;
239 elemsToExtract[1] = 0x1010;
240 elemsToExtract[2] = 0x0029;
241 elemsToExtract[3] = 0x1020;
245 /* if unused Param we give up */
246 if ( am->ArgMgrPrintUnusedLabels() )
248 am->ArgMgrUsage(usage);
252 delete am; // ------ we don't need Arguments Manager any longer ------
254 // ============================================================
255 // Read the input image.
256 // ============================================================
258 GDCM_NAME_SPACE::File *f = GDCM_NAME_SPACE::File::New( );
260 //f->SetLoadMode(GDCM_NAME_SPACE::LD_NOSEQ | GDCM_NAME_SPACE::LD_NOSHADOW);
261 f->SetFileName( fileName );
262 f->SetMaxSizeLoadEntry(0xffff);
263 bool res = f->Load();
265 if( GDCM_NAME_SPACE::Debug::GetDebugFlag())
267 std::cout << "---------------------------------------------" << std::endl;
269 std::cout << "---------------------------------------------" << std::endl;
272 std::cerr << "Sorry, " << fileName << " not a gdcm-readable "
273 << "DICOM / ACR File"
278 std::cout << " ... is readable " << std::endl;
281 // --------------------------------------------------------
285 // --------------------------------------------------------
287 // For each tag user wants to extract :
289 for (int tag_no=0; tag_no<extractNb; tag_no++) {
291 uint16_t group = elemsToExtract[2*tag_no];
292 uint16_t elem = elemsToExtract[2*tag_no+1];
295 std::cout << "Let's try tag : " << std::hex << group << "|" << elem << std::endl;
297 std::string dicom_tag_value = f->GetEntryString(group, elem);
298 if (dicom_tag_value == GDCM_NAME_SPACE::GDCM_UNFOUND)
300 GDCM_NAME_SPACE::DictEntry *dictEntry = f->GetPubDict()->GetEntry( group, elem);
301 if (dictEntry != NULL)
302 std::cerr << "Image doesn't contain any tag: " << dictEntry->GetName()
305 std::cerr << "Dicom Dictionary doesn't contain any tag: "
306 << std::hex << group << "|" << elem << std::endl;
311 GDCM_NAME_SPACE::DocEntry *dicom_tag_doc = f->GetDocEntry(group, elem);
312 GDCM_NAME_SPACE::DataEntry *dicom_tag = dynamic_cast<GDCM_NAME_SPACE::DataEntry *>(dicom_tag_doc);
315 std::cerr << "Sorry DataEntry only please" << std::endl;
320 // Write out the data as a file:
321 std::ofstream o(tempWorkFile);
324 std::cerr << "Problem opening file: [" << tempWorkFile << "]"
329 o.write((char*)dicom_tag->GetBinArea(), dicom_tag->GetLength());
335 std::ifstream is( tempWorkFile );
341 std::cout << dummy << std::endl;
342 if( strcmp( dummy, "SV10" ) )
344 std::cerr << "Either not a SV10 header or filled with 0..." << std::endl;
349 if( strcmp( dummy, "\4\3\2\1" ) )
351 std::cerr << "Either not a SV10 header or filled with 0..." << std::endl;
355 std::cout << (int)dummy[0] << (int)dummy[1] << (int)dummy[2]
356 << (int)dummy[3]<< std::endl;
359 is.read((char*)&n, sizeof(n));
361 std::cout << "number of entries " <<n << std::endl;
363 is.read((char*)&unused, sizeof(unused));
365 std::cout << "unused " << unused<< std::endl;
366 assert( unused == 77 ); // 'M' character...
368 for(uint32_t i = 0; i < n; ++i)
371 std::cout << "============================================== " << i <<
374 name[64] = 0; // security
375 //std::cout << "Pos 0x" << std::hex << is.tellg() << std::dec << std::endl;
378 std::cout << "Name=[" << name << "]" << std::endl;
380 is.read((char*)&vm, sizeof(vm));
382 std::cout << "vm=" << vm << std::endl;
386 assert( vr[2] == vr[3] && vr[2] == 0 );
389 std::cout << "vr=[" << vr << "]" <<std::endl;
391 is.read((char*)&syngodt, sizeof(syngodt));
392 check_mapping(syngodt, vr);
395 std::cout << "syngodt=" << syngodt << std::endl;
397 is.read((char*)&nitems, sizeof(nitems));
399 std::cout << "nitems=" << nitems<< std::endl;
401 is.read((char*)&xx, sizeof(xx));
402 //std::cout << "xx=" << xx<< std::endl;
403 assert( xx == 77 || xx == 205 );
405 myEntry = new CSA_entry;
406 myEntry->Name = name;
409 myEntry->Syngodt = syngodt;
410 myEntry->Nitems = nitems;
412 for( uint32_t j = 0; j < nitems; ++j)
415 std::cout << "-------------------------------------------- " << j
418 is.read((char*)&item_xx, 4*sizeof(uint32_t));
420 std::cout << std::dec
421 << "item_xx=" << item_xx[0] << " " << item_xx[1] << " "
422 << item_xx[2] << " " << item_xx[3] << std::endl;
423 //std::cout << "0x" << std::hex << is.tellg() << std::dec << std::endl;
424 assert( item_xx[2] == 77 || item_xx[2] == 205 );
425 uint32_t len = item_xx[1]; // 2nd element
427 std::cout << "len=" << len << std::endl;
428 assert( item_xx[0] == item_xx[1] && item_xx[1] == item_xx[3] );
429 char *val = new char[len+1];
430 val[len] = 0; // security
432 // WARNING vr does not means anything AFAIK,
433 // simply print the value as if it was IS/DS or LO (ASCII)
435 std::cout << "val=[" << val << "]" << std::endl;
438 uint32_t dummy_len = (4 - len % 4) % 4;
439 is.read(dummy, dummy_len );
442 for(uint32_t d= 0; d < dummy_len; ++d)
444 // I think dummy should always be 0
448 std::cout << "dummy=" << (int)dummy[d] << std::endl;
452 myItem = new CSA_item;
453 for (int i2=0; i2<4; i2++)
454 myItem->Item_xx[i2] = item_xx[i2];
458 myEntry->Items_set.push_back(myItem);
462 myMap[name] = myEntry;
465 std::cout << "================================================================"
467 << "=== Extract :" << std::hex << group << " " << elem << "========"
469 << "================================================================"
472 PrintCSA_content (myMap);
473 DeleteCSA_content (myMap);