]> Creatis software - gdcm.git/blob - Example/exExtractOverlaysDCM.cxx
306bb8c2a83be44e721eeb5d41517a0a517d8b85
[gdcm.git] / Example / exExtractOverlaysDCM.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: exExtractOverlaysDCM.cxx,v $
5   Language:  C++
6   Date:      $Date: 2007/10/30 09:15:58 $
7   Version:   $Revision: 1.5 $
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.
12                                                                                 
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.
16                                                                                 
17 =========================================================================*/
18 #include "gdcmFile.h"
19 #include "gdcmFileHelper.h"
20 #include "gdcmCommon.h"
21 #include "gdcmDebug.h"
22 #include "gdcmDataEntry.h"
23 #include "gdcmDirList.h"
24 #include "gdcmArgMgr.h"
25
26 #include <iostream>
27
28 // Each BIT of Overlay Data (0x60xx,0x3000) corresponds
29 // to a BYTE of overlay image.
30
31 void explodeByte(unsigned char byte, unsigned char* result)
32 {
33    unsigned char mask = 1;
34    for (int i=0;i<8;i++)
35    {
36       if ((byte & mask)==0)
37          result[i]=0;
38       else
39          result[i]=1;
40       mask<<=1;
41    }
42    return;
43 }
44
45 int main(int argc, char *argv[])
46 {
47    START_USAGE(usage)
48    " \n exExtractOverlaysDCM :\n                                              ",
49    " Extract DICOM style overlays from an image                               ",
50    "         Resulting image name(s) are postpended with .ovly.dcm            ",
51    " usage: exExtractOverlaysDCM filein=inputFileName  [debug] [warning]      ",
52    "        warning  : user wants to run the program in 'warning mode'        ",
53    "        debug    : developper wants to run the program in 'debug mode'    ",
54    FINISH_USAGE
55
56    // ----- Initialize Arguments Manager ------
57
58    GDCM_NAME_SPACE::ArgMgr *am = new GDCM_NAME_SPACE::ArgMgr(argc, argv);
59
60    if (argc == 1 || am->ArgMgrDefined("usage"))
61    {
62       am->ArgMgrUsage(usage); // Display 'usage'
63       delete am;
64       return 0;
65    }
66
67    const char *fileName  = am->ArgMgrWantString("filein", usage);
68
69    if (am->ArgMgrDefined("debug"))
70       GDCM_NAME_SPACE::Debug::DebugOn();
71
72    if (am->ArgMgrDefined("warning"))
73       GDCM_NAME_SPACE::Debug::WarningOn();
74
75    // if unused Param we give up
76    if ( am->ArgMgrPrintUnusedLabels() )
77    {
78       am->ArgMgrUsage(usage);
79       delete am;
80       return 0;
81    }
82
83    delete am;  // we don't need Argument Manager any longer
84
85    // ========================== Now, we can do the job! ================
86
87    GDCM_NAME_SPACE::File *f;
88
89 // ============================================================
90 //   Read the input image.
91 // ============================================================
92
93    f = GDCM_NAME_SPACE::File::New( );
94
95    f->AddForceLoadElement(0x6000,0x3000);  // Overlay Data
96    f->AddForceLoadElement(0x6002,0x3000); 
97    f->AddForceLoadElement(0x6004,0x3000); 
98    f->AddForceLoadElement(0x6006,0x3000);    
99    f->AddForceLoadElement(0x6008,0x3000);    
100    f->AddForceLoadElement(0x600a,0x3000); 
101    f->AddForceLoadElement(0x600c,0x3000); 
102    f->AddForceLoadElement(0x600e,0x3000);
103    f->AddForceLoadElement(0x6010,0x3000);
104    f->AddForceLoadElement(0x6012,0x3000);             
105    f->AddForceLoadElement(0x6014,0x3000);             
106    f->AddForceLoadElement(0x6016,0x3000); 
107    f->AddForceLoadElement(0x6018,0x3000); 
108    f->AddForceLoadElement(0x601a,0x3000);                
109    f->AddForceLoadElement(0x601c,0x3000); 
110    f->AddForceLoadElement(0x601e,0x3000); // Hope it's enought : Dicom says 60xx ...
111
112    f->SetLoadMode(GDCM_NAME_SPACE::LD_NOSEQ | GDCM_NAME_SPACE::LD_NOSHADOW);
113    f->SetFileName( fileName );
114    bool res = f->Load();
115
116    if (!res) {
117        std::cout << "Sorry, " << fileName <<"  not a gdcm-readable "
118            << "DICOM / ACR File"
119            <<std::endl;
120       f->Delete();
121       return 0;
122    }
123    std::cout << fileName << " ... is readable " << std::endl;
124
125 // ============================================================
126 //   Check whether image contains Overlays DICOM style.
127 // ============================================================
128
129    unsigned int nx = f->GetXSize();
130    unsigned int ny = f->GetYSize();
131    unsigned int nxy=nx*ny;
132    uint16_t currentOvlGroup;
133    int i;
134
135    std::ostringstream str;
136
137    uint8_t *outputData = new uint8_t[nxy]; // uint8 is enought to hold 1 bit !
138
139    GDCM_NAME_SPACE::File *fileToBuild = 0;
140    GDCM_NAME_SPACE::FileHelper *fh = 0;
141
142 // ============================================================
143 //   Get each overlay group into the image header
144 // ============================================================
145    for(i=0, currentOvlGroup=0x6000; i<32; i+=2 ,currentOvlGroup+=2)
146    {
147       GDCM_NAME_SPACE::DataEntry *e10 = f->GetDataEntry(currentOvlGroup, 0x0010); // nb Row Ovly
148       if (e10 == 0)
149       {
150          if( GDCM_NAME_SPACE::Debug::GetWarningFlag() )
151             std::cout << " Image doesn't contain Overlay on " <<std::hex
152                       << currentOvlGroup+i << std::endl;
153          continue;
154       }
155
156       GDCM_NAME_SPACE::DataEntry *e = f->GetDataEntry(currentOvlGroup, 0x3000);
157       if (e == 0)
158       {
159          if( GDCM_NAME_SPACE::Debug::GetWarningFlag() )
160             std::cout << " Image doesn't contain DICOM Overlay Data " <<std::hex
161                       << currentOvlGroup+i << std::endl;
162       }
163       else
164       {
165          uint8_t *overlay = (uint8_t *)(e->GetBinArea());
166          if ( overlay == 0 )
167          {
168             std::cerr << "Sorry, Overlays of [" << fileName << "] are not "
169                        << " gdcm-readable."    << std::endl;
170              continue;
171          }
172          if( GDCM_NAME_SPACE::Debug::GetWarningFlag() )
173             std::cout << " Overlay on group [" << std::hex << currentOvlGroup<< "] is read! " << std::endl;
174
175       // ============================================================
176       //  DICOM Overlay Image data generation
177       // ============================================================
178
179          unsigned char *result=outputData;
180          for (unsigned int i2=0;i2<(nxy/8);i2++)
181          {
182             explodeByte(overlay[i2], result);
183             result+=8;
184          }
185       }
186    // ============================================================
187    //   Write a new file
188    // ============================================================
189
190       fileToBuild = GDCM_NAME_SPACE::File::New();
191       str.str("");
192       str << nx;
193       fileToBuild->InsertEntryString(str.str(),0x0028,0x0011, "US"); // Columns
194       str.str("");
195       str << ny;
196       fileToBuild->InsertEntryString(str.str(),0x0028,0x0010, "US"); // Rows
197
198       fileToBuild->InsertEntryString("8",0x0028,0x0100, "US"); // Bits Allocated
199       fileToBuild->InsertEntryString("8",0x0028,0x0101, "US"); // Bits Stored
200       fileToBuild->InsertEntryString("7",0x0028,0x0102, "US"); // High Bit
201       fileToBuild->InsertEntryString("0",0x0028,0x0103, "US"); // Pixel Representation
202       fileToBuild->InsertEntryString("1",0x0028,0x0002, "US"); // Samples per Pixel
203       fileToBuild->InsertEntryString("MONOCHROME2 ",0x0028,0x0004, "LO");
204
205       // feel free to add any field (Dicom Data Entry) you like, here.
206       // ...
207       // Other mandatory fields will be set automatically,
208       // just before Write(), by FileHelper::CheckMandatoryElements()
209
210       fh = GDCM_NAME_SPACE::FileHelper::New(fileToBuild);
211
212       fh->SetImageData(outputData,nx*ny);
213       fh->SetWriteTypeToDcmExplVR();
214
215 std::ostringstream tmp;
216 tmp <<std::hex;
217 tmp <<currentOvlGroup;
218
219       str.str("");
220 // -> Why doesn't it work ?!?
221       //str << fileName << std::hex << currentOvlGroup << ".dcm" << std::ends;
222
223 str << fileName << ".ovly." << tmp.str() << ".dcm" << std::ends;
224
225       //   Write the current 'overlay' file
226
227       if( !fh->Write(str.str()) )
228       {
229          std::cout << "Failed\n"
230                    << "File [" << str.str() << "] is unwrittable" << std::endl;
231       }
232       else
233       {
234          std::cout << "File written successfully [" << str.str()  << "]" << std::endl;
235       }
236
237    } // end on loop on 60xx
238
239    if (f)
240       fh->Delete();
241    if (fileToBuild)
242       fileToBuild->Delete();
243    f->Delete();
244
245    return 0;
246 }
247