Program: gdcm
Module: $RCSfile: exExtractOverlaysDCM.cxx,v $
Language: C++
- Date: $Date: 2007/09/12 10:43:47 $
- Version: $Revision: 1.1 $
+ Date: $Date: 2009/05/28 15:44:34 $
+ Version: $Revision: 1.6 $
Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
l'Image). All rights reserved. See Doc/License.txt or
PURPOSE. See the above copyright notices for more information.
=========================================================================*/
-
-
#include "gdcmFile.h"
#include "gdcmFileHelper.h"
#include "gdcmCommon.h"
#include "gdcmDebug.h"
#include "gdcmDataEntry.h"
#include "gdcmDirList.h"
-
#include "gdcmArgMgr.h"
+
#include <iostream>
-// Each BIT of Overlay Data (0x6000,0x3000) corresponds
+// Each BIT of Overlay Data (0x60xx,0x3000) corresponds
// to a BYTE of overlay image.
-void explodeByte(unsigned char byte, unsigned char* result)
+
+void explodeByte(unsigned char byte, unsigned char* result)
{
unsigned char mask = 1;
- for (int i=0;i<8;i++)
+ for (int i=0;i<8;i++)
{
- if ((byte & mask)==0)
+ if ((byte & mask)==0)
result[i]=0;
- else
+ else
result[i]=1;
mask<<=1;
}
return;
}
-
int main(int argc, char *argv[])
{
START_USAGE(usage)
- " \n ExtractOverlays :\n ",
- " Extract overlay images from all DICOM image within a directory ",
- " Warning : probably segfaults if no overlay ",
- " usage: ExtractOverlays dirin=inputDirectoryName [debug] ",
+ " \n exExtractOverlaysDCM :\n ",
+ " Extract DICOM style overlays from an image ",
+ " Resulting image name(s) are postpended with .ovly.dcm ",
+ " usage: exExtractOverlaysDCM filein=inputFileName [debug] [warning] ",
+ " warning : user wants to run the program in 'warning 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 (argc == 1 || am->ArgMgrDefined("usage"))
delete am;
return 0;
}
-
- const char *dirIn = am->ArgMgrWantString("dirin", usage);
+
+ const char *fileName = am->ArgMgrWantString("filein", usage);
if (am->ArgMgrDefined("debug"))
GDCM_NAME_SPACE::Debug::DebugOn();
-
+
if (am->ArgMgrDefined("warning"))
GDCM_NAME_SPACE::Debug::WarningOn();
-
+
// if unused Param we give up
if ( am->ArgMgrPrintUnusedLabels() )
{
delete am; // we don't need Argument Manager any longer
+ // ========================== Now, we can do the job! ================
- // ========================== Now, we can do the job! ================
-
+ GDCM_NAME_SPACE::File *f;
- // ======================== more checking on the params ==============
+// ============================================================
+// Read the input image.
+// ============================================================
- if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirIn) )
- {
- std::cout << "KO : [" << dirIn << "] is not a Directory." << std::endl;
- return 0;
+ f = GDCM_NAME_SPACE::File::New( );
- }
-
- char outputFileName[1024]; // Hope it's enough for a file name!
-
- GDCM_NAME_SPACE::File *f;
-
- GDCM_NAME_SPACE::DirList dirList(dirIn,true); // gets (recursively) the file list
- GDCM_NAME_SPACE::DirListType fileList = dirList.GetFilenames();
- for( GDCM_NAME_SPACE::DirListType::iterator it = fileList.begin();
- it != fileList.end();
- ++it )
- {
- // Just to see *all* the file names:
- // std::cout << "file [" << it->c_str() << "]" << std::endl;
-
- // Read the input file.
-
- if( GDCM_NAME_SPACE::Debug::GetWarningFlag() )
- std::cerr << "Deal with [" << it->c_str()
- << "] File" <<std::endl;
-
- f = GDCM_NAME_SPACE::File::New( );
- f->SetLoadMode( GDCM_NAME_SPACE::LD_ALL );
- f->SetFileName( it->c_str() );
-
f->AddForceLoadElement(0x6000,0x3000); // Overlay Data
f->AddForceLoadElement(0x6002,0x3000);
f->AddForceLoadElement(0x6004,0x3000);
f->AddForceLoadElement(0x601a,0x3000);
f->AddForceLoadElement(0x601c,0x3000);
f->AddForceLoadElement(0x601e,0x3000); // Hope it's enought : Dicom says 60xx ...
-
- int res = f->Load();
- if ( !res )
- {
- std::cerr << "Sorry, " << it->c_str() <<" not a gdcm-readable "
- << "DICOM / ACR File" <<std::endl;
- f->Delete();
- continue;
+ f->SetLoadMode(GDCM_NAME_SPACE::LD_NOSEQ | GDCM_NAME_SPACE::LD_NOSHADOW);
+ f->SetFileName( fileName );
+ bool res = f->Load();
+
+ if (!res) {
+ std::cout << "Sorry, " << fileName <<" not a gdcm-readable "
+ << "DICOM / ACR File"
+ <<std::endl;
+ f->Delete();
+ return 0;
}
+ std::cout << fileName << " ... is readable " << std::endl;
- if( GDCM_NAME_SPACE::Debug::GetWarningFlag() )
- std::cout << " ... is readable " << std::endl;
+// ============================================================
+// Check whether image contains Overlays DICOM style.
+// ============================================================
- // ============================================================
- // Load Overlay info in memory
- // ============================================================
+ unsigned int nx = f->GetXSize();
+ unsigned int ny = f->GetYSize();
+ unsigned int nxy=nx*ny;
+ uint16_t currentOvlGroup;
+ int i;
-/// \todo : deal with *each* overlay Data Element (not only the first one!)
+ std::ostringstream str;
- uint16_t ovlyGroup = 0x6000;
-
- for (int k=0; k<32; k+=2)
- {
+ uint8_t *outputData = new uint8_t[nxy]; // uint8 is enought to hold 1 bit !
- GDCM_NAME_SPACE::DataEntry *e10 = f->GetDataEntry(ovlyGroup+k, 0x0010); // nb Row Ovly
- if (e10 == 0)
- {
- if( GDCM_NAME_SPACE::Debug::GetWarningFlag() )
- std::cout << " Image doesn't contain Overlay on " <<std::hex
- << ovlyGroup+k << std::endl;
- continue;
- }
-
- // ============================================================
- // Image data preparation
- // ============================================================
-
- unsigned int dimX= f->GetXSize();
- unsigned int dimY= f->GetYSize();
- unsigned int dimXY=dimX*dimY;
-
- unsigned char *outputData = new unsigned char[dimXY];
-
-
- GDCM_NAME_SPACE::DataEntry *e = f->GetDataEntry(ovlyGroup+k, 0x3000);
- if (e == 0)
- {
- if( GDCM_NAME_SPACE::Debug::GetWarningFlag() )
- std::cout << " Image doesn't contain DICOM Overlay Data " <<std::hex
- << ovlyGroup+k << std::endl;
-
- // ============================================================
- // DICOM Overlay Image data generation
- // ============================================================
+ GDCM_NAME_SPACE::File *fileToBuild = 0;
+ GDCM_NAME_SPACE::FileHelper *fh = 0;
- GDCM_NAME_SPACE::FileHelper *fh = GDCM_NAME_SPACE::FileHelper::New(f);
- uint8_t *pixelData= fh->GetImageDataRaw();
-
- if (pixelData == 0)
- {
- std::cerr << "Sorry, Pixel Data of [" << it->c_str() <<"] are not "
- << " gdcm-readable." << std::endl;
- continue;
- }
-
- }
- else
+// ============================================================
+// Get each overlay group into the image header
+// ============================================================
+ for(i=0, currentOvlGroup=0x6000; i<32; i+=2 ,currentOvlGroup+=2)
{
- uint8_t *overlay = (uint8_t *)(e->GetBinArea());
- if ( overlay == 0 )
+ GDCM_NAME_SPACE::DataEntry *e10 = f->GetDataEntry(currentOvlGroup, 0x0010); // nb Row Ovly
+ if (e10 == 0)
{
- std::cerr << "Sorry, Overlays of [" << it->c_str() <<"] are not "
- << " gdcm-readable." << std::endl;
- continue;
+ if( GDCM_NAME_SPACE::Debug::GetWarningFlag() )
+ std::cout << " Image doesn't contain Overlay on " <<std::hex
+ << currentOvlGroup+i << std::endl;
+ continue;
}
- if( GDCM_NAME_SPACE::Debug::GetWarningFlag() )
- std::cout << " Overlay on group [" << std::hex << ovlyGroup+k << "] is read! " << std::endl;
-
+
+ GDCM_NAME_SPACE::DataEntry *e = f->GetDataEntry(currentOvlGroup, 0x3000);
+ if (e == 0)
+ {
+ if( GDCM_NAME_SPACE::Debug::GetWarningFlag() )
+ std::cout << " Image doesn't contain DICOM Overlay Data " <<std::hex
+ << currentOvlGroup+i << std::endl;
+ }
+ else
+ {
+ uint8_t *overlay = (uint8_t *)(e->GetBinArea());
+ if ( overlay == 0 )
+ {
+ std::cerr << "Sorry, Overlays of [" << fileName << "] are not "
+ << " gdcm-readable." << std::endl;
+ continue;
+ }
+ if( GDCM_NAME_SPACE::Debug::GetWarningFlag() )
+ std::cout << " Overlay on group [" << std::hex << currentOvlGroup<< "] is read! " << std::endl;
+
// ============================================================
// DICOM Overlay Image data generation
- // ============================================================
-
+ // ============================================================
- unsigned char *result=outputData;
- for (unsigned int i=0;i<(dimXY/8);i++)
- {
- explodeByte(overlay[i], result);
- result+=8;
+ unsigned char *result=outputData;
+ for (unsigned int i2=0;i2<(nxy/8);i2++)
+ {
+ explodeByte(overlay[i2], result);
+ result+=8;
+ }
}
- }
// ============================================================
// Write a new file
// ============================================================
-
- GDCM_NAME_SPACE::File *f2;
- f2 = GDCM_NAME_SPACE::File::New( );
- GDCM_NAME_SPACE::FileHelper *fh2 = GDCM_NAME_SPACE::FileHelper::New(f2);
-
- char temp[256];
-
- sprintf(temp,"%d ",dimX);
- f2->InsertEntryString(temp,0x0028,0x0011, "US"); // Columns
- sprintf(temp,"%d ",dimY);
- f2->InsertEntryString(temp,0x0028,0x0010, "US"); // Rows
- f2->InsertEntryString("8",0x0028,0x0100, "US"); // Bits Allocated
- f2->InsertEntryString("8",0x0028,0x0101, "US"); // Bits Stored
- f2->InsertEntryString("7",0x0028,0x0102, "US"); // High Bit
- f2->InsertEntryString("0",0x0028,0x0103, "US"); // Pixel Representation
- f2->InsertEntryString("1",0x0028,0x0002, "US"); // Samples per Pixel
- f2->InsertEntryString("MONOCHROME2 ",0x0028,0x0004, "LO");
-
- // feel free to add any field (Dicom Data Entry) you like, here.
- // ...
-
- sprintf(outputFileName, "../%s.ovly.%04x.dcm",it->c_str(), ovlyGroup+k);
-
- fh2->SetImageData(outputData,dimXY);
- fh2->WriteDcmExplVR(outputFileName);
-
- std::cout <<"File written successfully [" << outputFileName << "]" <<std::endl;
-
- delete outputData;
- f2->Delete();
- fh2->Delete();
-
- } // end on loop on 60xx
-
+
+ fileToBuild = GDCM_NAME_SPACE::File::New();
+ str.str("");
+ str << nx;
+ fileToBuild->InsertEntryString(str.str(),0x0028,0x0011, "US"); // Columns
+ str.str("");
+ str << ny;
+ fileToBuild->InsertEntryString(str.str(),0x0028,0x0010, "US"); // Rows
+
+ fileToBuild->InsertEntryString("8",0x0028,0x0100, "US"); // Bits Allocated
+ fileToBuild->InsertEntryString("8",0x0028,0x0101, "US"); // Bits Stored
+ fileToBuild->InsertEntryString("7",0x0028,0x0102, "US"); // High Bit
+ fileToBuild->InsertEntryString("0",0x0028,0x0103, "US"); // Pixel Representation
+ fileToBuild->InsertEntryString("1",0x0028,0x0002, "US"); // Samples per Pixel
+ fileToBuild->InsertEntryString("MONOCHROME2 ",0x0028,0x0004, "LO");
+
+ // feel free to add any field (Dicom Data Entry) you like, here.
+ // ...
+ // Other mandatory fields will be set automatically,
+ // just before Write(), by FileHelper::CheckMandatoryElements()
+
+ fh = GDCM_NAME_SPACE::FileHelper::New(fileToBuild);
+
+ fh->SetImageData(outputData,nx*ny);
+ fh->SetWriteTypeToDcmExplVR();
+
+std::ostringstream tmp;
+tmp <<std::hex;
+tmp <<currentOvlGroup;
+
+ str.str("");
+// -> Why doesn't it work ?!?
+ //str << fileName << std::hex << currentOvlGroup << ".dcm" << std::ends;
+
+str << fileName << ".ovly." << tmp.str() << ".dcm" << std::ends;
+
+ // Write the current 'overlay' file
+
+ if( !fh->Write(str.str()) )
+ {
+ std::cout << "Failed\n"
+ << "File [" << str.str() << "] is unwrittable" << std::endl;
+ }
+ else
+ {
+ std::cout << "File written successfully [" << str.str() << "]" << std::endl;
+ }
+
+ } // end on loop on 60xx
+
+ if (fh)
+ fh->Delete();
+ if (fileToBuild)
+ fileToBuild->Delete();
f->Delete();
-
-} // end of loop on files ( DirListType::iterator )
-
return 0;
}