/*========================================================================= Program: gdcm Module: $RCSfile: exExtractCSA.cxx,v $ Language: C++ Date: $Date: 2007/10/03 09:14:55 $ Version: $Revision: 1.8 $ Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de l'Image). All rights reserved. See Doc/License.txt or http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notices for more information. =========================================================================*/ /* * http://www.enac.northwestern.edu/~tew/archives/2003/02/25/incomplete-dicom-headers/ * http://www.nmr.mgh.harvard.edu/~rudolph/software/vox2ras/download/vox2ras_rsolve.m * http://www.mail-archive.com/freesurfer@nmr.mgh.harvard.edu/msg03409.html * http://www.mmrrcc.upenn.edu/CAMRIS/cfn/dicomhdr.html */ // See this one : // http://www.mmrrcc.upenn.edu/CAMRIS/cfn/dicomhdr.html #include #include #include #include #include #include #include "gdcmFile.h" #include "gdcmFileHelper.h" #include "gdcmCommon.h" #include "gdcmDebug.h" #include "gdcmDocEntry.h" #include "gdcmDataEntry.h" #include "gdcmSeqEntry.h" #include "gdcmSQItem.h" #include "gdcmArgMgr.h" // -------------------------------------------------------- typedef struct { uint32_t Item_xx[4]; int Len; std::string Value; } CSA_item; typedef std::vector ItemVector; typedef struct { std::string Name; int VM; std::string VR; int Syngodt; int Nitems; ItemVector Items_set; } CSA_entry; typedef std::map CSA_content; // -------------------------------------------------------- struct equ { uint32_t syngodt; char vr[2+1]; }; // Looks like there is mapping in between syngodt and vr... // O <=> UN // 3 <=> DS // 4 <=> FD // 5 <=> FL // 6 <=> IS // 9 <=> UL // 10 <=> US // 16 <=> CS // 19 <=> LO // 20 <=> LT // 22 <=> SH // 25 <=> UI static equ mapping[] = { { 0 , "UN" }, { 3 , "DS" }, { 4 , "FD" }, { 5 , "FL" }, { 6 , "IS" }, { 7 , "SL" }, { 8 , "SS" }, { 9 , "UL" }, { 10 , "US" }, { 16 , "CS" }, { 19 , "LO" }, { 20 , "LT" }, { 22 , "SH" }, { 23 , "ST" }, { 25 , "UI" }, { 27 , "UT" } }; bool check_mapping(uint32_t syngodt, const char *vr) { static const unsigned int max = sizeof(mapping) / sizeof(equ); unsigned int s = 0; const equ *p = mapping; assert( syngodt <= mapping[max-1].syngodt ); while(p->syngodt < syngodt ) { //std::cout << "mapping:" << p->vr << std::endl; ++p; } assert( p->syngodt == syngodt ); // or else need to update mapping const char* lvr = p->vr; int check = strcmp(vr, lvr) == 0; assert( check ); return true; } ///\to fix the Destructor! void DeleteCSA_content (CSA_content &myMap) { for ( CSA_content::const_iterator it = myMap.begin(); it != myMap.end(); ++it) { ItemVector item_v = (*it).second->Items_set; for ( ItemVector::const_iterator it2 = item_v.begin(); it2 != item_v.end(); ++it2) { // delete (*it2); } //delete (*it).second; } } void PrintCSA_content(CSA_content &myMap) { int item_no; for ( CSA_content::const_iterator it = myMap.begin(); it != myMap.end(); ++it) { std::cout << "[" << (*it).second->Name << "] : VR=[" << (*it).second->VR << "] vm = " << (*it).second->VM << std::endl; item_no = 0; ItemVector item_v = (*it).second->Items_set; for ( ItemVector::const_iterator it2 = item_v.begin(); it2 != item_v.end(); ++it2) { std::cout << " --- item no : " << item_no << std::endl; std::cout << " Item_xxx : " << (*it2)->Item_xx[0] << " " << (*it2)->Item_xx[1] << " " << (*it2)->Item_xx[2] << " " << (*it2)->Item_xx[3] << std::endl; std::cout << " Len = " << (*it2)->Len ; std::cout << " Value = [" << (*it2)->Value << "]" << std::endl; item_no++; } } } int main(int argc, char *argv[]) { START_USAGE(usage) "\n exExtractCSA :\n ", "Extracts and displays the CSA tag(s) of gdcm-parsable Dicom file ", " ", "usage: exExtractCSA {filein=inputFileName|dirin=inputDirectoryName} ", " tmp=temporaryWorkFileName ", " [extract=listOfElementsToExtract] ", " [ { [noshadowseq] | [noshadow][noseq] } ] [debug] ", " inputFileName : Name of the (single) file user wants to anonymize ", " listOfElementsExtract : group-elem,g2-e2,... (in hexa, no space) ", " of Elements to extract ", " default : 0029-1010,0029-1020 ", " noshadowseq: user doesn't want to load Private Sequences ", " noshadow : user doesn't want to load Private groups (odd number) ", " noseq : user doesn't want to load Sequences ", " verbose : developper wants to run the program in 'verbose mode' ", " debug : developper wants to run the program in 'debug mode' ", FINISH_USAGE // ----- Initialize Arguments Manager ------ GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv); if (am->ArgMgrDefined("usage") || argc == 1) { am->ArgMgrUsage(usage); // Display 'usage' delete am; return 1; } if (am->ArgMgrDefined("debug")) GDCM_NAME_SPACE::Debug::DebugOn(); bool verbose = am->ArgMgrDefined("verbose"); const char *fileName = am->ArgMgrGetString("filein"); int loadMode = GDCM_NAME_SPACE::LD_ALL; if ( am->ArgMgrDefined("noshadowseq") ) loadMode |= GDCM_NAME_SPACE::LD_NOSHADOWSEQ; else { if ( am->ArgMgrDefined("noshadow") ) loadMode |= GDCM_NAME_SPACE::LD_NOSHADOW; if ( am->ArgMgrDefined("noseq") ) loadMode |= GDCM_NAME_SPACE::LD_NOSEQ; } const char *tempWorkFile = am->ArgMgrGetString("tmp"); int extractNb; uint16_t *elemsToExtract; if (am->ArgMgrDefined("extract")) { am->ArgMgrGetXInt16Enum("extract", &extractNb); std::cout << "extractNb=" << extractNb << std::endl; if (extractNb =! 0) for (int k=0;kArgMgrPrintUnusedLabels() ) { am->ArgMgrUsage(usage); delete am; return 1; } delete am; // ------ we don't need Arguments Manager any longer ------ // ============================================================ // Read the input image. // ============================================================ GDCM_NAME_SPACE::File *f = GDCM_NAME_SPACE::File::New( ); //f->SetLoadMode(GDCM_NAME_SPACE::LD_NOSEQ | GDCM_NAME_SPACE::LD_NOSHADOW); f->SetFileName( fileName ); f->SetMaxSizeLoadEntry(0xffff); bool res = f->Load(); if( GDCM_NAME_SPACE::Debug::GetDebugFlag()) { std::cout << "---------------------------------------------" << std::endl; f->Print(); std::cout << "---------------------------------------------" << std::endl; } if (!res) { std::cerr << "Sorry, " << fileName << " not a gdcm-readable " << "DICOM / ACR File" << std::endl; f->Delete(); return 1; } std::cout << " ... is readable " << std::endl; // -------------------------------------------------------- CSA_content myMap; CSA_entry *myEntry; CSA_item *myItem; // -------------------------------------------------------- // For each tag user wants to extract : for (int tag_no=0; tag_noGetEntryString(group, elem); if (dicom_tag_value == GDCM_NAME_SPACE::GDCM_UNFOUND) { GDCM_NAME_SPACE::DictEntry *dictEntry = f->GetPubDict()->GetEntry( group, elem); if (dictEntry != NULL) std::cerr << "Image doesn't contain any tag: " << dictEntry->GetName() << std::endl; else std::cerr << "Dicom Dictionary doesn't contain any tag: " << std::hex << group << "|" << elem << std::endl; f->Delete(); return 1; } GDCM_NAME_SPACE::DocEntry *dicom_tag_doc = f->GetDocEntry(group, elem); GDCM_NAME_SPACE::DataEntry *dicom_tag = dynamic_cast(dicom_tag_doc); if( !dicom_tag ) { std::cerr << "Sorry DataEntry only please" << std::endl; f->Delete(); return 1; } // Write out the data as a file: std::ofstream o(tempWorkFile); if( !o ) { std::cerr << "Problem opening file: [" << tempWorkFile << "]" << std::endl; f->Delete(); return 1; } o.write((char*)dicom_tag->GetBinArea(), dicom_tag->GetLength()); o.close(); //#define OLDFORMAT std::ifstream is( tempWorkFile ); #ifndef OLDFORMAT char dummy[4+1]; dummy[4] = 0; is.read(dummy, 4); if (verbose) std::cout << dummy << std::endl; if( strcmp( dummy, "SV10" ) ) { std::cerr << "Either not a SV10 header or filled with 0..." << std::endl; return 1; } // wotsit ? is.read(dummy, 4); if( strcmp( dummy, "\4\3\2\1" ) ) { std::cerr << "Either not a SV10 header or filled with 0..." << std::endl; return 1; } if (verbose) std::cout << (int)dummy[0] << (int)dummy[1] << (int)dummy[2] << (int)dummy[3]<< std::endl; #endif uint32_t n; is.read((char*)&n, sizeof(n)); if (verbose) std::cout << "number of entries " <Delete(); return 0; }