]> Creatis software - gdcm.git/blob - Example/RawToDicom.cxx
Typo
[gdcm.git] / Example / RawToDicom.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: RawToDicom.cxx,v $
5   Language:  C++
6   Date:      $Date: 2007/03/23 15:01:47 $
7   Version:   $Revision: 1.9 $
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
19 /**
20  * Writes a Dicom file from a Raw File
21  * User has to supply parameters. 
22  * 
23  */
24 #include "gdcmFile.h"
25 #include "gdcmFileHelper.h"
26 #include "gdcmDebug.h"
27 #include "gdcmUtil.h"
28 #include "gdcmArgMgr.h"
29
30 #include <iostream>
31 #include <sstream>
32
33 void ConvertSwapZone(int pixelSize, void *Raw, size_t RawSize);
34
35 void ConvertSwapZone(int pixelSize, void *Raw, size_t RawSize)
36 {
37    unsigned int i;    
38    if ( pixelSize == 2 )
39    {
40       uint16_t *im16 = (uint16_t*)Raw;
41       for( i = 0; i < RawSize / 2; i++ )
42       {
43          im16[i]= (im16[i] >> 8) | (im16[i] << 8 );
44       }     
45    }
46    else if ( pixelSize == 4 )
47    {
48       uint32_t s32;
49       uint16_t high;
50       uint16_t low;
51       uint32_t *im32 = (uint32_t*)Raw;
52
53       for( i = 0; i < RawSize / 4; i++ )
54       {
55          low     = im32[i] & 0x0000ffff; // 3412
56          high    = im32[i] >> 16;
57          s32     = low;
58          im32[i] = ( s32 << 16 ) | high;
59       }
60       
61    }
62 }
63
64
65
66 int main(int argc, char *argv[])
67 {
68    START_USAGE(usage)
69    " \n RawToDicom : \n                                                       ",
70    " Writes a Dicom file from a Raw File                                      ",
71    " usage: RawToDicom filein=inputFileName                                   ",
72    "                   fileout=outputFileName                                 ",
73    "                   rows=nb of Rows                                        ",
74    "                   lines=nb of Lines,                                     ",
75    "                   pixeltype={8U|8S|16U|16S|32U|32S}                      ",
76    "                   [{b|l}] b:BigEndian,l:LittleEndian default : l         ",
77    "                   [frames = nb of Frames] //defaulted to 1               ",
78    "                   [samples = {1|3}}       //defaulted to 1(1:Gray,3:RGB) ",
79    "                   [patientname = Patient's name]                         ",
80    "                   [debug]                                                ",
81    "                                                                          ",
82    "      debug      : developper wants to run the program in 'debug mode'    ",
83    FINISH_USAGE
84    
85
86    // Initialize Arguments Manager   
87    gdcm::ArgMgr *am= new gdcm::ArgMgr(argc, argv);
88   
89    if (argc == 1 || am->ArgMgrDefined("usage") )
90    {
91       am->ArgMgrUsage(usage); // Display 'usage'
92       delete am;
93       return 1;
94    }
95
96    const char *inputFileName  = am->ArgMgrGetString("filein");
97    const char *outputFileName = am->ArgMgrGetString("fileout");
98    
99    const char *patientName = am->ArgMgrGetString("patientname");
100    
101    int nX = am->ArgMgrWantInt("rows", usage);
102    int nY = am->ArgMgrWantInt("lines", usage);
103    int nZ = am->ArgMgrGetInt("frames", 1);
104    int samplesPerPixel = am->ArgMgrGetInt("samples", 1);
105    
106    int b = am->ArgMgrDefined("b");
107    int l = am->ArgMgrDefined("l");
108       
109    char *pixelType = am->ArgMgrWantString("pixeltype", usage);
110    
111    if (am->ArgMgrDefined("debug"))
112       gdcm::Debug::DebugOn();
113
114    /* if unused Param we give up */
115    if ( am->ArgMgrPrintUnusedLabels() )
116    {
117       am->ArgMgrUsage(usage);
118       delete am;
119       return 1;
120    } 
121
122    delete am;  // we don't need Argument Manager any longer
123
124    // ----------- End Arguments Manager ---------
125    
126   
127  // Read the Raw file  
128    std::ifstream *Fp = new std::ifstream(inputFileName, std::ios::in | std::ios::binary);
129    if ( ! *Fp )
130    {   
131       std::cout << "Cannot open file: " << inputFileName;
132       delete Fp;
133       Fp = 0;
134       return 0;
135    }  
136
137    bool bigEndian = gdcm::Util::IsCurrentProcessorBigEndian();
138
139    std::string strPixelType(pixelType);
140    int pixelSign;
141    int pixelSize;
142    
143    if (strPixelType == "8S")
144    {
145       pixelSize = 1;
146       pixelSign = 1;
147    }
148    else if (strPixelType == "8U")
149    {
150       pixelSize = 1;
151       pixelSign = 0;
152    }
153    else if (strPixelType == "16S")
154    {
155       pixelSize = 2;
156       pixelSign = 1; 
157    }   
158    else if (strPixelType == "16U")
159    {
160       pixelSize = 2;
161       pixelSign = 0;
162    }      
163    else if (strPixelType == "32S")
164    {
165       pixelSize = 4;
166       pixelSign = 1;
167    }   
168    else if (strPixelType == "32U")
169    {
170       pixelSize = 4;
171       pixelSign = 0;
172    }
173    else
174    {
175       std::cout << "Wrong 'pixeltype' (" << strPixelType << ")" << std::endl;
176       return 1;
177    }
178    
179    int dataSize =  nX*nY*nZ*pixelSize*samplesPerPixel;
180    uint8_t *pixels = new uint8_t[dataSize];
181    
182    Fp->read((char*)pixels, (size_t)dataSize);
183      
184    if ( pixelSize !=1 && ( (l && bigEndian) || (b && ! bigEndian) ) )
185    {  
186       ConvertSwapZone(pixelSize, pixels, dataSize);   
187    }
188    
189    
190 // Create an empty FileHelper
191
192    gdcm::FileHelper *fileH = gdcm::FileHelper::New();
193  
194  // Get the (empty) image header.  
195    gdcm::File *fileToBuild = fileH->GetFile();
196      
197    
198    // If you want to use this program as a template to create
199    // a 'Single Study UID - Single Serie UID' file set
200    // keep the following lines out of the loop
201
202    // 'Study Instance UID'
203    // The user is allowed to create his own Study, 
204    //          keeping the same 'Study Instance UID' for various images
205    // The user may add images to a 'Manufacturer Study',
206    //          adding new Series to an already existing Study
207    std::string studyUID =  gdcm::Util::CreateUniqueUID(); 
208    fileToBuild->InsertEntryString(studyUID, 0x0020,0x000d,"UI");
209
210    // 'Serie Instance UID'
211    // The user is allowed to create his own Series, 
212    // keeping the same 'Serie Instance UID' for various images
213    // The user shouldn't add any image to a 'Manufacturer Serie'
214    // but there is no way no to prevent him for doing that
215    std::string serieUID =  gdcm::Util::CreateUniqueUID();    
216    fileToBuild->InsertEntryString(serieUID, 0x0020,0x000e,"UI");   
217  
218    // end of 'keep out of loop lines  
219    
220    std::ostringstream str;
221
222    // Set the image size
223    str.str("");
224    str << nX;
225    fileToBuild->InsertEntryString(str.str(),0x0028,0x0011, "US"); // Columns
226    str.str("");
227    str << nY;
228    fileToBuild->InsertEntryString(str.str(),0x0028,0x0010, "US"); // Rows
229    
230    str.str("");
231    str << nZ;
232    fileToBuild->InsertEntryString(str.str(),0x0028,0x0008, "IS"); // Number of Frames
233
234    // Set the pixel type
235    
236    str.str("");
237    str << pixelSize*8;
238    fileToBuild->InsertEntryString(str.str(),0x0028,0x0100, "US"); // Bits Allocated
239
240    str.str("");
241    str << pixelSize*8;
242    fileToBuild->InsertEntryString(str.str(),0x0028,0x0101, "US"); // Bits Stored
243
244    str.str("");
245    str << ( pixelSize*8 - 1 );
246    fileToBuild->InsertEntryString(str.str(),0x0028,0x0102, "US"); // High Bit
247
248    str.str("");
249    str << pixelSign;
250    fileToBuild->InsertEntryString(str.str(),0x0028,0x0103, "US"); // Pixel Representation
251
252    str.str("");
253    str << samplesPerPixel;
254    
255 // If you deal with a Serie of images, it up to you to tell gdcm,
256 // for each image, what are the values of :
257 // 0020 0032 DS 3 Image Position (Patient)
258 // 0020 0037 DS 6 Image Orientation (Patient)
259
260    fileToBuild->InsertEntryString(str.str(),0x0028,0x0002, "US"); // Samples per Pixel
261
262    if (strlen(patientName) != 0)
263       fileToBuild->InsertEntryString(patientName,0x0010,0x0010, "PN"); // Patient's Name
264    
265    
266 // Set the image Pixel Data
267    fileH->SetImageData(pixels,dataSize);
268
269 // Set the writting mode and write the image
270    fileH->SetWriteModeToRaw();
271
272  // Write a DICOM Explicit VR file
273    fileH->SetWriteTypeToDcmExplVR();
274
275    if( !fileH->Write(outputFileName ) )
276    {
277       std::cout << "Failed for [" << outputFileName << "]\n"
278                 << "           File is unwrittable\n";
279    }
280
281    fileH->Delete();
282
283    delete[] pixels;
284    return 1;
285 }