/*========================================================================= Program: gdcm Module: $RCSfile: exPresentationState.cxx,v $ Language: C++ Date: $Date: 2009/05/25 14:29:16 $ Version: $Revision: 1.2 $ 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. =========================================================================*/ #include "gdcmFile.h" // ---------- //#include "gdcmValEntry.h" #include "gdcmDataEntry.h" // ---------- #include "gdcmSeqEntry.h" #include "gdcmSQItem.h" #include "gdcmDocEntrySet.h" #include "gdcmSerieHelper.h" #include "gdcmDirList.h" #include "gdcmUtil.h" #include "gdcmArgMgr.h" GDCM_NAME_SPACE::SeqEntry *CheckIfSequenceExists(GDCM_NAME_SPACE::File *fPS, uint16_t gr, uint16_t el); GDCM_NAME_SPACE::SeqEntry *CheckIfSequenceExists(GDCM_NAME_SPACE::SQItem *si, uint16_t gr, uint16_t el); bool dealWithTopLevelItem(GDCM_NAME_SPACE::SQItem* currentItem); bool dealWithEndLevelItem(GDCM_NAME_SPACE::SQItem* currentItem); void displaySeekResult(GDCM_NAME_SPACE::SeqEntry* currentItem, uint16_t g, uint16_t e); void dealWithSequence(GDCM_NAME_SPACE::SeqEntry* se); // ------------------------------------------------------------------------------------------------------- int main(int argc, char *argv[]) { START_USAGE(usage) "\n exPresentationState :\n ", "Extracts and displays the Graphic annotation / Text Objet Sequences of gdcm-parsable Dicom file", " ", "usage: exPresentationState {filein=inputFileName|dirin=inputDirectoryName}", " [ { [noshadowseq] | [noshadow][noseq] } ] [debug] ", " filein : Name of the image file ", " PSFile : Name of the PresentationState file : ", " 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 0; } if (am->ArgMgrDefined("debug")) GDCM_NAME_SPACE::Debug::DebugOn(); bool verbose = am->ArgMgrDefined("verbose"); const char *fileName = am->ArgMgrGetString("filein"); const char *PSName = am->ArgMgrGetString("PSfile"); /* if unused Param we give up */ if ( am->ArgMgrPrintUnusedLabels() ) { am->ArgMgrUsage(usage); delete am; return 0; } 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; */ // ================================================================================= GDCM_NAME_SPACE::File *fPS = GDCM_NAME_SPACE::File::New( ); fPS->SetFileName( PSName ); fPS->SetMaxSizeLoadEntry(0xffff); bool res2 = fPS->Load(); if (!res2) { std::cout << "Sorry, " << PSName << " not a gdcm-readable " << "DICOM / ACR File" << std::endl; f->Delete(); return 1; } GDCM_NAME_SPACE::SeqEntry *se; se = CheckIfSequenceExists( fPS, 0x0070, 0x0001); //displaySeekResult(se, 0x0070, 0x0001); if (!se) { std::cout << "Hopeless : " << std::hex << 0x0070 << "|" << 0x0001 << std::dec << " doesn't exist..." <GetFirstSQItem(); // Get the first 'ROI' int i =0; while (currentItem != NULL) { std::cout << "======== Deal With 'ROI' n." << i << std::endl; // do what you want with the current 'ROI' dealWithTopLevelItem(currentItem); //... currentItem = se->GetNextSQItem(); // Get the next 'ROI' i++; } /* bool res3 = TestPresentationState(f, fPS); if (res3) { std::cout << "[" << PSName << "] is a gdcm-readable PresentationState file" <Delete(); fPS->Delete(); return 0; } //---------------------------------------------------------------------------------------------------- bool dealWithTopLevelItem(GDCM_NAME_SPACE::SQItem* currentItem) { // probably this list should be cleaned up. // (I didn't find the exact architecture of Presentation State) int tabElement[] = { 0x0008, 0x0009, 0x005a, 0x0060, 0x0086, 0x0308, 0x0309, 0x030A, 0x030d, 0x0311, 0x0314, 0x0318, 0x031c, 0x031e, 0x0402, 0x0404, 0x0000 }; bool res = false; GDCM_NAME_SPACE::SeqEntry *se; se = CheckIfSequenceExists(currentItem, 0x0008, 0x1140); displaySeekResult(se, 0x0008, 0x1140); if (se != 0) { res = true; dealWithSequence(se); } for(int i=0; tabElement[i]!=0x0000; i++) { se = CheckIfSequenceExists(currentItem, 0x0070, tabElement[i]); displaySeekResult(se, 0x0070, tabElement[i]); if (se != 0) { res = true; dealWithSequence(se); } } return (res); } //---------------------------------------------------------------------------------------------------- bool dealWithEndLevelItem(GDCM_NAME_SPACE::SQItem* currentItem) { // probably this list should be cleaned up, too. // (I didn't find the exact architecture of Presentation State) int tabElement[] = { 0x0008, 0x0009, 0x005a, 0x0060, 0x0086, 0x0308, 0x0309, 0x030A, 0x030d, 0x0311, 0x0314, 0x0318, 0x031c, 0x031e, 0x0402, 0x0404, 0x0000 }; bool res = false; GDCM_NAME_SPACE::SeqEntry *se; se = CheckIfSequenceExists(currentItem, 0x0008, 0x1140); displaySeekResult(se, 0x0008, 0x1140); if (se != 0) { res = true; dealWithSequence(se); } for(int i=0; tabElement[i]!=0x0000; i++) { se = CheckIfSequenceExists(currentItem, 0x0070, tabElement[i]); displaySeekResult(se, 0x0070, tabElement[i]); if (se != 0) { res = true; dealWithSequence(se); } } return (res); } //---------------------------------------------------------------------------------------------------- void dealWithSequence(GDCM_NAME_SPACE::SeqEntry* se) { uint16_t g = se->GetGroup(); uint16_t e = se->GetElement(); std::cout << std::hex << "\n------------------------ deal with " << g <<"|" << e << std::dec << " " << se->GetName() << std::endl; GDCM_NAME_SPACE::SQItem *si = se->GetFirstSQItem(); if (!si) { std::cout << "Sequence " << std::hex << g <<"|" << e << std::dec << "has no Item ?!?" << std::endl; return; } if (g == 0x0008) { si->Print(std::cout); } else if (g == 0x0070) { si->Print(std::cout); } else { std::cout << "Unexpected Group " << std::hex << g << std::hex << std::endl; } si = se->GetNextSQItem(); if (si) { std::cout << "Sequence " << std::hex << g <<"|" << e << std::dec << "should have only ONE Item ?!?" << std::endl; si->Print(std::cout); return; } } //---------------------------------------------------------------------------------------------------- void displaySeekResult(GDCM_NAME_SPACE::SeqEntry* se, uint16_t g, uint16_t e) { if (se) { // std::cout << std::hex << g << "|" << e << std::dec << " [" << se->GetName() << "] exists" <GetSeqEntry(gr, el); return se; } // ---------------------------------------------------------------------------------- GDCM_NAME_SPACE::SeqEntry *CheckIfSequenceExists( GDCM_NAME_SPACE::SQItem *si, uint16_t gr, uint16_t el) { GDCM_NAME_SPACE::SeqEntry *se= si->GetSeqEntry(gr, el); return se; }