]> Creatis software - gdcm.git/blob - Testing/TestWriteSimple.cxx
Fix mistypings
[gdcm.git] / Testing / TestWriteSimple.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   gdcm
4   Module:    $RCSfile: TestWriteSimple.cxx,v $
5   Language:  C++
6   Date:      $Date: 2007/09/28 14:20:22 $
7   Version:   $Revision: 1.53 $
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  * Write a dicom file from nothing
21  * The written image is 256x256, 8 bits, unsigned char
22  * The image content is a horizontal grayscale from 
23  * 
24  */
25 #include "gdcmFile.h"
26 #include "gdcmFileHelper.h"
27 #include "gdcmDebug.h"
28 #include "gdcmGlobal.h"
29 #include "gdcmDictSet.h"
30
31 #include <iostream>
32 #include <sstream>
33
34 typedef struct
35 {
36    int sizeX;         // Size X of the image
37    int sizeY;         // Size Y of the image
38    int sizeZ;         // Size Z of the image
39    int components;    // Number of components for a pixel
40    int componentSize; // Component size (in bits : 8, 16) // Bits Allocated
41    int componentUse ; // Component size (in bits)         // Bits Stored
42    int sign;          // Sign of components
43    char writeMode;    // Write mode
44                       //  - 'a' : ACR
45                       //  - 'e' : Explicit VR
46                       //  - 'i' : Implicit VR
47 } Image;
48
49 Image Images [] = {
50 // these ones are use to check further oddities.
51
52    {63, 127, 1, 1, 16,  8,  0 ,'e'},
53    {63, 127, 1, 1, 16,  9,  0 ,'e'},
54    {63, 127, 1, 1, 16, 10,  0 ,'e'},
55    {63, 127, 1, 1, 16, 11,  0 ,'e'},
56    {63, 127, 1, 1, 16, 12,  0 ,'e'},
57    {63, 127, 1, 1, 16, 13,  0 ,'e'},
58    {63, 127, 1, 1, 16, 14,  0 ,'e'},
59    {63, 127, 1, 1, 16, 15,  0 ,'e'}, 
60    {63, 127, 1, 1, 16, 16,  0 ,'e'},
61    
62    {63, 127, 1, 1, 32, 32,  0 ,'e'},   // Pixel VR should be OL?
63       
64    {128, 128, 1, 1, 8,  8,  0, 'e'},
65    {256, 128, 1, 1, 8,  8,  0, 'a'},
66    {128, 128, 1, 1, 8,  8,  0, 'i'},
67
68    {128, 128, 1, 1, 8,  8,  0, 'a'},    
69    {256, 128, 1, 1, 8,  8,  0, 'i'},
70      
71
72    {256, 128, 1, 1, 8,  8,  0, 'e'},
73    {128, 128, 1, 1, 16, 16, 0, 'e'},      
74    {128, 256, 1, 1, 16, 16, 0, 'e'},   
75    
76    {128, 256, 1, 1, 8,  8,  0, 'e'},
77    {128, 256, 1, 1, 8,  8,  0, 'i'},
78    {128, 256, 1, 1, 8,  8,  0, 'a'},
79    
80    {128, 256, 1, 1, 16, 16, 0, 'i'},
81    {128, 256, 1, 1, 16, 16, 0, 'i'},
82    {128, 256, 1, 1, 16, 16, 0, 'a'},
83    {128, 256, 1, 1, 16, 16, 0, 'a'},
84
85    {256, 128, 10, 1, 8, 8,  0, 'e'},
86    {256, 128, 10, 3, 8, 8,  0, 'e'},
87    {256, 128, 10, 3, 8, 8,  0, 'i'},
88    {256, 128, 10, 1, 8, 8,  0, 'i'},
89    {256, 128, 10, 1, 8, 8,  0, 'a'},
90    {256, 128, 10, 3, 8, 8,  0, 'a'},
91       
92    {128, 128, 1, 1, 8,  8,  1, 'e'},
93    {128, 128, 1, 1, 8,  8,  1, 'i'},
94    {128, 128, 1, 1, 8,  8,  1, 'a'},
95    
96    {256, 128, 1, 1, 8,  8,  1, 'e'},
97    {256, 128, 1, 1, 8,  8,  1, 'i'},
98    {256, 128, 1, 1, 8,  8,  1, 'a'},
99    
100    {128, 256, 1, 1, 8,  8,  1, 'a'},
101    {128, 256, 1, 1, 8,  8,  1, 'e'},
102    {128, 256, 1, 1, 8,  8,  1, 'i'},
103
104    {128, 256, 1, 1, 16, 16, 1, 'e'},
105    {128, 256, 1, 1, 16, 16, 1, 'e'},
106    {128, 256, 1, 1, 16, 16, 1, 'i'},
107    {128, 256, 1, 1, 16, 16, 1, 'i'},
108    {128, 256, 1, 1, 16, 16, 1, 'a'},
109    {128, 256, 1, 1, 16, 16, 1, 'a'},     
110
111    {256, 128, 10, 1, 8, 8,  1, 'e'},
112    {256, 128, 10, 1, 8, 8,  1, 'i'},
113    {256, 128, 10, 1, 8, 8,  1, 'a'},   
114    
115    {256, 128, 10, 3, 8, 8,  1, 'e'},
116    {256, 128, 10, 3, 8, 8,  1, 'i'},
117    {256, 128, 10, 3, 8, 8,  1, 'a'},
118    {0,   0,   1,  1, 8, 8,  0, 'i'} // to find the end
119 };
120
121
122 const unsigned int MAX_NUMBER_OF_DIFFERENCE = 10;
123
124 int WriteSimple(Image &img)
125 {
126    
127    std::cout << "======================= WriteSimple =========(begin of processing current image)" << std::endl;
128    std::ostringstream fileName;
129    fileName.str("");
130    fileName << "TestWriteSimple";
131
132 // Step 1 : Create an empty FileHelper
133
134    std::cout << "        1...";
135    GDCM_NAME_SPACE::FileHelper *fileH = GDCM_NAME_SPACE::FileHelper::New();
136  
137  //  Get the (empty) image header.  
138    GDCM_NAME_SPACE::File *fileToBuild = fileH->GetFile();
139    std::ostringstream str;
140
141    // Set the image size
142    str.str("");
143    str << img.sizeX;
144    fileToBuild->InsertEntryString(str.str(),0x0028,0x0011,"US"); // Columns
145    str.str("");
146    str << img.sizeY;
147    fileToBuild->InsertEntryString(str.str(),0x0028,0x0010,"US"); // Rows
148
149    if(img.sizeZ>1)
150    {
151       str.str("");
152       str << img.sizeZ;
153       fileToBuild->InsertEntryString(str.str(),0x0028,0x0008, "IS"); // Number of Frames
154    }
155
156    fileName << "-" << img.sizeX << "-" << img.sizeY << "-" << img.sizeZ;
157
158    // Set the pixel type
159    str.str("");
160    str << img.componentSize;
161    fileToBuild->InsertEntryString(str.str(),0x0028,0x0100,"US"); // Bits Allocated
162
163    str.str("");
164    str << img.componentUse;
165    fileToBuild->InsertEntryString(str.str(),0x0028,0x0101,"US"); // Bits Stored
166
167    str.str("");
168    str << ( img.componentUse - 1 );
169    fileToBuild->InsertEntryString(str.str(),0x0028,0x0102,"US"); // High Bit
170
171    // Set the pixel representation
172    str.str("");
173    str << img.sign;
174    fileToBuild->InsertEntryString(str.str(),0x0028,0x0103,"US"); // Pixel Representation
175
176    fileName << "-" << img.componentSize;
177    if(img.sign == 0)
178       fileName << "U";
179    else
180       fileName << "S";
181       
182    fileName << "-" << img.componentSize << "-" << img.componentUse;
183  
184    fileToBuild->InsertEntryString("0",0x0008,0x0000,"UL"); // Should be removed
185                                                             // except for ACR 
186    switch (img.writeMode)
187    {
188       case 'a' :
189          fileName << ".ACR";
190          break; 
191       case 'e' :
192          fileName << ".EXPL"; 
193          break; 
194       case 'i' :
195          fileName << ".IMPL"; 
196          break;
197    } 
198
199    if(img.componentSize == 32)
200    {
201       // Create a Private DataElement; VR =OL
202       fileToBuild->InsertEntryString("gdcm test OL",0x0009,0x0010,"LO");
203       uint32_t binArea[4];
204       binArea[0] = 0x01234567;
205       binArea[1] = 0x89abcdef;      
206       binArea[2] = 0x2468ace0;
207       binArea[2] = 0xfdb97531;
208       fileToBuild->InsertEntryBinArea((uint8_t *)binArea,16,0x0009,0x0100,"OL");              
209    }
210    
211    
212    std::cout << "[" << fileName.str() << "]...";
213    // Set the samples per pixel
214    str.str("");
215    str << img.components;
216    fileToBuild->InsertEntryString(str.str(),0x0028,0x0002,"US"); // Samples per Pixel
217
218 // Step 2 : Create the output image
219    std::cout << "2...";
220    if( img.componentSize%8 > 0 )
221    {
222       img.componentSize += 8-img.componentSize%8;
223    }
224    size_t size = img.sizeX * img.sizeY * img.sizeZ 
225                * img.components * img.componentSize / 8;
226    unsigned char *imageData = new unsigned char[size];
227
228    // FIXME : find a better heuristic to create the image
229    unsigned char *tmp = imageData;
230    for(int k=0;k<img.sizeZ;k++)
231    {
232       for(int j=0;j<img.sizeY;j++)
233       {
234          for(int i=0;i<img.sizeX;i++)
235          {
236             for(int c=0;c<img.components;c++)
237             {
238                *tmp = (unsigned char)(j%256);
239                if( img.componentSize>8 )
240                {
241                   *(tmp+1) = (unsigned char)(j/256);
242                }
243                tmp += img.componentSize/8;
244             }
245          }
246       }
247    }
248
249 // Step 3 : Set the image Pixel Data
250    std::cout << "3...";
251    fileH->SetImageData(imageData,size);
252
253 // Step 4 : Set the writting mode and write the image
254
255    fileH->SetWriteModeToRaw();
256    std::cout << "4'...";   
257    switch (img.writeMode)
258    {
259       case 'a' : // Write an ACR file
260          fileH->SetWriteTypeToAcr();
261          break;
262
263       case 'e' : // Write a DICOM Explicit VR file
264          fileH->SetWriteTypeToDcmExplVR();
265          break;
266
267       case 'i' : // Write a DICOM Implicit VR file
268          fileH->SetWriteTypeToDcmImplVR();
269          break;
270
271       default :
272          std::cout << "Failed for [" << fileName.str() << "]\n"
273                    << "        Write mode '"<<img.writeMode<<"' is undefined\n";
274
275          fileH->Delete();
276          delete[] imageData;
277          return 1;
278    }
279
280    std::cout << std::endl;
281    //fileToBuild->Print();
282
283    if( !fileH->Write(fileName.str()) )
284    {
285       std::cout << "Failed for [" << fileName.str() << "]\n"
286                 << "           File is unwrittable" << std::endl;
287
288       fileH->Delete();
289
290       delete[] imageData;
291       return 1;
292    }
293
294 // Step 5 : Read the written image
295    std::cout << "5..." << std::endl;
296    // old form.
297    //GDCM_NAME_SPACE::FileHelper *reread = new GDCM_NAME_SPACE::FileHelper( fileName.str() );
298    // Better use :
299    GDCM_NAME_SPACE::File *f = GDCM_NAME_SPACE::File::New( );
300    f->SetLoadMode(GDCM_NAME_SPACE::LD_ALL);
301    f->SetFileName( fileName.str() );
302    
303    //reread->SetFileName( fileName.str() );
304    //reread->SetLoadMode(GDCM_NAME_SPACE::LD_ALL); // Load everything
305                            // Possible values are 
306                            //              GDCM_NAME_SPACE::LD_ALL, 
307                            //              GDCM_NAME_SPACE::LD_NOSEQ, 
308                            //              GDCM_NAME_SPACE::LD_NOSHADOW,
309                            //              GDCM_NAME_SPACE::LD_NOSEQ|GDCM_NAME_SPACE::LD_NOSHADOW, 
310                            //              GDCM_NAME_SPACE::LD_NOSHADOWSEQ
311    
312    f->Load();
313   // reread->Load();
314    GDCM_NAME_SPACE::FileHelper *reread = GDCM_NAME_SPACE::FileHelper::New( f );  
315
316    //reread->Print();
317
318    if( !reread->GetFile()->IsReadable() )
319    {
320       std::cerr << "Failed" << std::endl
321                 << "Could not read written image : " << fileName.str() << std::endl;
322       fileToBuild->Delete();
323       fileH->Delete();
324       reread->Delete();
325       delete[] imageData;
326       return 1;
327    }
328
329 // Step 6 : Compare to the written image
330    std::cout << "6..." << std::endl;
331    size_t dataSizeWritten = reread->GetImageDataSize();
332    uint8_t *imageDataWritten = reread->GetImageData();
333
334    // Test the image write mode
335    if (reread->GetFile()->GetFileType() != fileH->GetWriteType())
336    {
337       std::cout << "Failed" << std::endl
338          << "        File type differ: "
339          << fileH->GetWriteType() << " # " 
340          << reread->GetFile()->GetFileType() << std::endl;
341       fileToBuild->Delete();
342       fileH->Delete();
343       reread->Delete();
344       delete[] imageData;
345
346       return 1;
347    }
348    std::cout << "6.1..." << std::endl;
349    // Test the image size
350    if (fileToBuild->GetXSize() != reread->GetFile()->GetXSize() ||
351        fileToBuild->GetYSize() != reread->GetFile()->GetYSize() ||
352        fileToBuild->GetZSize() != reread->GetFile()->GetZSize())
353    {
354       std::cout << "Failed for [" << fileName.str() << "]" << std::endl
355          << "        X Size differs: "
356          << "X: " << fileToBuild->GetXSize() << " # " 
357                   << reread->GetFile()->GetXSize() << " | "
358          << "Y: " << fileToBuild->GetYSize() << " # " 
359                   << reread->GetFile()->GetYSize() << " | "
360          << "Z: " << fileToBuild->GetZSize() << " # " 
361                   << reread->GetFile()->GetZSize() << std::endl;
362       fileToBuild->Delete();
363       fileH->Delete();
364       reread->Delete();
365       delete[] imageData;
366
367       return 1;
368    }
369  std::cout << "6.2..." << std::endl;
370    // Test the data size
371    if (size != dataSizeWritten)
372    {
373       std::cout << "Failed" << std::endl
374          << "        Pixel areas lengths differ: "
375          << size << " # " << dataSizeWritten << std::endl;
376       fileToBuild->Delete();
377       fileH->Delete();
378       reread->Delete();
379       delete[] imageData;
380
381       return 1;
382    }
383 std::cout << "6.3..." << std::endl;
384    // Test the data content
385    if ( memcmp(imageData, imageDataWritten, size) !=0 )
386    {
387       std::cout << fileName.str() << " Failed " << std::endl
388                 << "        Pixel differ (as expanded in memory)." << std::endl;
389       std::cout << "        list of the first " << MAX_NUMBER_OF_DIFFERENCE
390                   << " pixels differing (pos : test - ref) :" 
391                   << std::endl;
392       unsigned int i;
393       unsigned int j;
394       for(i=0, j=0;i<dataSizeWritten && j<MAX_NUMBER_OF_DIFFERENCE;i++)
395       {
396          if(imageDataWritten[i]!=imageData[i])
397             {
398             std::cout << std::hex << "(" << i << " : " 
399                         << std::hex << (int)(imageDataWritten[i]) << " - "
400                         << std::hex << (int)(imageData[i]) << ") "
401                         << std::dec;
402             ++j;
403             }
404       }
405       std::cout << std::endl;
406       fileToBuild->Delete();
407       fileH->Delete();
408       reread->Delete();
409       delete[] imageData;
410
411       return 1;
412    }
413 std::cout << "======================= OK" << std::endl;
414    fileH->Delete();
415    reread->Delete();
416    delete[] imageData;
417    return 0;
418 }
419
420 int TestWriteSimple(int argc, char *argv[])
421 {
422    if (argc < 1) 
423    {
424       std::cerr << "usage: \n" 
425                 << argv[0] << " (without parameters) " << std::endl 
426                 << std::endl;
427       return 1;
428    }
429
430   // GDCM_NAME_SPACE::Debug::DebugOn();
431
432    int ret=0;
433    int i=0;
434    while( Images[i].sizeX>0 && Images[i].sizeY>0 )
435    {
436       std::cout << "Test n :" << i <<std::endl;; 
437       ret += WriteSimple(Images[i] );
438       i++;
439
440    }
441
442    return ret;
443 }