1 /*=========================================================================
4 Module: $RCSfile: exExtractOverlaysDCM.cxx,v $
6 Date: $Date: 2007/09/12 10:43:47 $
7 Version: $Revision: 1.1 $
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 =========================================================================*/
21 #include "gdcmFileHelper.h"
22 #include "gdcmCommon.h"
23 #include "gdcmDebug.h"
24 #include "gdcmDataEntry.h"
25 #include "gdcmDirList.h"
27 #include "gdcmArgMgr.h"
30 // Each BIT of Overlay Data (0x6000,0x3000) corresponds
31 // to a BYTE of overlay image.
32 void explodeByte(unsigned char byte, unsigned char* result)
34 unsigned char mask = 1;
47 int main(int argc, char *argv[])
50 " \n ExtractOverlays :\n ",
51 " Extract overlay images from all DICOM image within a directory ",
52 " Warning : probably segfaults if no overlay ",
53 " usage: ExtractOverlays dirin=inputDirectoryName [debug] ",
54 " debug : developper wants to run the program in 'debug mode' ",
57 // ----- Initialize Arguments Manager ------
59 GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
61 if (argc == 1 || am->ArgMgrDefined("usage"))
63 am->ArgMgrUsage(usage); // Display 'usage'
68 const char *dirIn = am->ArgMgrWantString("dirin", usage);
70 if (am->ArgMgrDefined("debug"))
71 GDCM_NAME_SPACE::Debug::DebugOn();
73 if (am->ArgMgrDefined("warning"))
74 GDCM_NAME_SPACE::Debug::WarningOn();
76 // if unused Param we give up
77 if ( am->ArgMgrPrintUnusedLabels() )
79 am->ArgMgrUsage(usage);
84 delete am; // we don't need Argument Manager any longer
87 // ========================== Now, we can do the job! ================
90 // ======================== more checking on the params ==============
92 if ( ! GDCM_NAME_SPACE::DirList::IsDirectory(dirIn) )
94 std::cout << "KO : [" << dirIn << "] is not a Directory." << std::endl;
99 char outputFileName[1024]; // Hope it's enough for a file name!
101 GDCM_NAME_SPACE::File *f;
103 GDCM_NAME_SPACE::DirList dirList(dirIn,true); // gets (recursively) the file list
104 GDCM_NAME_SPACE::DirListType fileList = dirList.GetFilenames();
105 for( GDCM_NAME_SPACE::DirListType::iterator it = fileList.begin();
106 it != fileList.end();
109 // Just to see *all* the file names:
110 // std::cout << "file [" << it->c_str() << "]" << std::endl;
112 // Read the input file.
114 if( GDCM_NAME_SPACE::Debug::GetWarningFlag() )
115 std::cerr << "Deal with [" << it->c_str()
116 << "] File" <<std::endl;
118 f = GDCM_NAME_SPACE::File::New( );
119 f->SetLoadMode( GDCM_NAME_SPACE::LD_ALL );
120 f->SetFileName( it->c_str() );
122 f->AddForceLoadElement(0x6000,0x3000); // Overlay Data
123 f->AddForceLoadElement(0x6002,0x3000);
124 f->AddForceLoadElement(0x6004,0x3000);
125 f->AddForceLoadElement(0x6006,0x3000);
126 f->AddForceLoadElement(0x6008,0x3000);
127 f->AddForceLoadElement(0x600a,0x3000);
128 f->AddForceLoadElement(0x600c,0x3000);
129 f->AddForceLoadElement(0x600e,0x3000);
130 f->AddForceLoadElement(0x6010,0x3000);
131 f->AddForceLoadElement(0x6012,0x3000);
132 f->AddForceLoadElement(0x6014,0x3000);
133 f->AddForceLoadElement(0x6016,0x3000);
134 f->AddForceLoadElement(0x6018,0x3000);
135 f->AddForceLoadElement(0x601a,0x3000);
136 f->AddForceLoadElement(0x601c,0x3000);
137 f->AddForceLoadElement(0x601e,0x3000); // Hope it's enought : Dicom says 60xx ...
143 std::cerr << "Sorry, " << it->c_str() <<" not a gdcm-readable "
144 << "DICOM / ACR File" <<std::endl;
149 if( GDCM_NAME_SPACE::Debug::GetWarningFlag() )
150 std::cout << " ... is readable " << std::endl;
152 // ============================================================
153 // Load Overlay info in memory
154 // ============================================================
156 /// \todo : deal with *each* overlay Data Element (not only the first one!)
158 uint16_t ovlyGroup = 0x6000;
160 for (int k=0; k<32; k+=2)
163 GDCM_NAME_SPACE::DataEntry *e10 = f->GetDataEntry(ovlyGroup+k, 0x0010); // nb Row Ovly
166 if( GDCM_NAME_SPACE::Debug::GetWarningFlag() )
167 std::cout << " Image doesn't contain Overlay on " <<std::hex
168 << ovlyGroup+k << std::endl;
172 // ============================================================
173 // Image data preparation
174 // ============================================================
176 unsigned int dimX= f->GetXSize();
177 unsigned int dimY= f->GetYSize();
178 unsigned int dimXY=dimX*dimY;
180 unsigned char *outputData = new unsigned char[dimXY];
183 GDCM_NAME_SPACE::DataEntry *e = f->GetDataEntry(ovlyGroup+k, 0x3000);
186 if( GDCM_NAME_SPACE::Debug::GetWarningFlag() )
187 std::cout << " Image doesn't contain DICOM Overlay Data " <<std::hex
188 << ovlyGroup+k << std::endl;
190 // ============================================================
191 // DICOM Overlay Image data generation
192 // ============================================================
194 GDCM_NAME_SPACE::FileHelper *fh = GDCM_NAME_SPACE::FileHelper::New(f);
195 uint8_t *pixelData= fh->GetImageDataRaw();
199 std::cerr << "Sorry, Pixel Data of [" << it->c_str() <<"] are not "
200 << " gdcm-readable." << std::endl;
207 uint8_t *overlay = (uint8_t *)(e->GetBinArea());
210 std::cerr << "Sorry, Overlays of [" << it->c_str() <<"] are not "
211 << " gdcm-readable." << std::endl;
214 if( GDCM_NAME_SPACE::Debug::GetWarningFlag() )
215 std::cout << " Overlay on group [" << std::hex << ovlyGroup+k << "] is read! " << std::endl;
217 // ============================================================
218 // DICOM Overlay Image data generation
219 // ============================================================
222 unsigned char *result=outputData;
223 for (unsigned int i=0;i<(dimXY/8);i++)
225 explodeByte(overlay[i], result);
229 // ============================================================
231 // ============================================================
233 GDCM_NAME_SPACE::File *f2;
234 f2 = GDCM_NAME_SPACE::File::New( );
235 GDCM_NAME_SPACE::FileHelper *fh2 = GDCM_NAME_SPACE::FileHelper::New(f2);
239 sprintf(temp,"%d ",dimX);
240 f2->InsertEntryString(temp,0x0028,0x0011, "US"); // Columns
241 sprintf(temp,"%d ",dimY);
242 f2->InsertEntryString(temp,0x0028,0x0010, "US"); // Rows
243 f2->InsertEntryString("8",0x0028,0x0100, "US"); // Bits Allocated
244 f2->InsertEntryString("8",0x0028,0x0101, "US"); // Bits Stored
245 f2->InsertEntryString("7",0x0028,0x0102, "US"); // High Bit
246 f2->InsertEntryString("0",0x0028,0x0103, "US"); // Pixel Representation
247 f2->InsertEntryString("1",0x0028,0x0002, "US"); // Samples per Pixel
248 f2->InsertEntryString("MONOCHROME2 ",0x0028,0x0004, "LO");
250 // feel free to add any field (Dicom Data Entry) you like, here.
253 sprintf(outputFileName, "../%s.ovly.%04x.dcm",it->c_str(), ovlyGroup+k);
255 fh2->SetImageData(outputData,dimXY);
256 fh2->WriteDcmExplVR(outputFileName);
258 std::cout <<"File written successfully [" << outputFileName << "]" <<std::endl;
264 } // end on loop on 60xx
269 } // end of loop on files ( DirListType::iterator )