]> Creatis software - clitk.git/blob - common/clitkVoxImageIO.cxx
With ITK 5, add itkReadRawBytesAfterSwappingMacro and itkWriteRawBytesAfterSwappingMacro
[clitk.git] / common / clitkVoxImageIO.cxx
1 /*=========================================================================
2   Program:   vv                     http://www.creatis.insa-lyon.fr/rio/vv
3
4   Authors belong to:
5   - University of LYON              http://www.universite-lyon.fr/
6   - Léon Bérard cancer center       http://www.centreleonberard.fr
7   - CREATIS CNRS laboratory         http://www.creatis.insa-lyon.fr
8
9   This software is distributed WITHOUT ANY WARRANTY; without even
10   the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
11   PURPOSE.  See the copyright notices for more information.
12
13   It is distributed under dual licence
14
15   - BSD        See included LICENSE.txt file
16   - CeCILL-B   http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
17 ===========================================================================**/
18 #ifndef CLITKVOXIMAGEIO_CXX
19 #define CLITKVOXIMAGEIO_CXX
20 /**
21    -------------------------------------------------
22    * @file   clitkVoxImageIO.cxx
23    * @author David Sarrut <david.sarrut@creatis.insa-lyon.fr>
24    * @date   17 May 2006 08:03:07
25    *
26    * @brief
27    *
28    *
29    -------------------------------------------------*/
30
31 // clitk include
32 #include "clitkVoxImageIO.h"
33 #include "clitkCommon.h"
34
35 // itk include (for itkReadRawBytesAfterSwappingMacro)
36 #if ( ITK_VERSION_MAJOR < 5 )
37 #include "itkRawImageIO.h"
38 #else
39 #include <itkByteSwapper.h>
40 #endif
41
42 //--------------------------------------------------------------------
43 // Read Image Information
44 void clitk::VoxImageIO::ReadImageInformation()
45 {
46   // open file
47   std::ifstream is;
48   clitk::openFileForReading(is, m_FileName);
49   // read magic number
50   std::string mn;
51   is >> mn;
52   //DD(mn);
53   if (mn != "VOX") {
54     itkExceptionMacro(<<"read magic number '" << mn << "' while expect VOX");
55   }
56   // read vox file version
57   skipComment(is);
58   is >> mn;
59   //DD(mn);
60   if (mn != "v2") {
61     itkExceptionMacro(<<"read old format '" << mn << "'. TODO");
62   }
63
64   // ONLY 3D IMAGES YET ...
65
66   // read grid size/spacing
67   itk::Vector<unsigned int,3> dim;
68   itk::Vector<double,3> spacing;
69   itk::Vector<double,3> origin;
70   origin.Fill(0.0);
71   skipComment(is);
72   is >> dim[0];
73   is >> dim[1];
74   is >> dim[2];
75   //DD(dim);
76   skipComment(is);
77   is >> spacing[0];
78   is >> spacing[1];
79   is >> spacing[2];
80   //DD(spacing);
81   skipComment(is);
82   int d;
83   is >> d;
84   if (d != 3 && d != 2) {
85     itkExceptionMacro(<<"could not read no " << d << "D image (only 2D and 3D). TODO");
86   }
87   // read data type
88   skipComment(is);
89   std::string dataTypeName;
90   is >> dataTypeName;
91   //DD(dataTypeName);
92
93   // get header size
94   m_HeaderSize = is.tellg();
95   m_HeaderSize++;
96   //DD(m_HeaderSize);
97
98   // set dimension values
99   SetNumberOfDimensions(d);
100   for(int i=0; i<d; i++) {
101     SetDimensions(i,dim[i]);
102     SetSpacing(i,spacing[i]);
103     SetOrigin(i,origin[i]);
104   }
105
106   // set other information
107   SetByteOrderToLittleEndian();
108   SetPixelType(itk::ImageIOBase::SCALAR);
109   SetNumberOfComponents(1);
110
111   if (dataTypeName == "char") SetComponentType(itk::ImageIOBase::CHAR);
112   else if (dataTypeName == "schar") SetComponentType(itk::ImageIOBase::CHAR);
113   else if (dataTypeName == "uchar" || dataTypeName == "unsigned_char") SetComponentType(itk::ImageIOBase::UCHAR);
114   else if (dataTypeName == "sshort") SetComponentType(itk::ImageIOBase::SHORT);
115   else if (dataTypeName == "ushort") SetComponentType(itk::ImageIOBase::USHORT);
116   else if (dataTypeName == "int") SetComponentType(itk::ImageIOBase::INT);
117   else if (dataTypeName == "sint") SetComponentType(itk::ImageIOBase::INT);
118   else if (dataTypeName == "uint") SetComponentType(itk::ImageIOBase::UINT);
119   else if (dataTypeName == "float") SetComponentType(itk::ImageIOBase::FLOAT);
120   else if (dataTypeName == "double") SetComponentType(itk::ImageIOBase::DOUBLE);
121   else {
122     itkExceptionMacro(<<"Read failed: Wanted pixel type "
123                       << "(char, uchar, short, ushort, int, uint, float, double)"
124                       << " but read " << dataTypeName);
125   }
126
127 } ////
128
129 //--------------------------------------------------------------------
130 // Read Image Information
131 bool clitk::VoxImageIO::CanReadFile(const char* FileNameToRead)
132 {
133   std::string filename(FileNameToRead);
134   std::string filenameext = GetExtension(filename);
135   if (filenameext != std::string("vox")) return false;
136   return true;
137 } ////
138
139 //--------------------------------------------------------------------
140 // Read Image Content
141 void clitk::VoxImageIO::Read(void * buffer)
142 {
143   // Adapted from itkRawImageIO
144
145   std::ifstream file;
146   openFileForReading(file, m_FileName);
147
148   // Offset into file
149   unsigned long streamStart = m_HeaderSize;
150   file.seekg((long)streamStart, std::ios::beg);
151   if ( file.fail() ) {
152     itkExceptionMacro(<<"File seek failed (Vox Read)");
153   }
154
155   unsigned long numberOfBytesToBeRead = GetComponentSize();
156   for(unsigned int i=0; i<GetNumberOfDimensions(); i++) numberOfBytesToBeRead *= GetDimensions(i);
157
158   //DD(numberOfBytesToBeRead);
159
160   if(!this->ReadBufferAsBinary(file, buffer, numberOfBytesToBeRead)) {
161     itkExceptionMacro(<<"Read failed: Wanted "
162                       << numberOfBytesToBeRead
163                       << " bytes, but read "
164                       << file.gcount() << " bytes.");
165   }
166   itkDebugMacro(<< "Reading Done");
167
168   {
169 #if ( ITK_VERSION_MAJOR < 5 )
170     using namespace itk;
171     // Swap bytes if necessary
172     if itkReadRawBytesAfterSwappingMacro( unsigned short, USHORT )
173       else if itkReadRawBytesAfterSwappingMacro( short, SHORT )
174         else if itkReadRawBytesAfterSwappingMacro( char, CHAR )
175           else if itkReadRawBytesAfterSwappingMacro( unsigned char, UCHAR )
176             else if itkReadRawBytesAfterSwappingMacro( unsigned int, UINT )
177               else if itkReadRawBytesAfterSwappingMacro( int, INT )
178                 else if itkReadRawBytesAfterSwappingMacro( float, FLOAT )
179                   else if itkReadRawBytesAfterSwappingMacro( double, DOUBLE );
180 #else
181   #define itkReadRawBytesAfterSwappingMacro(StrongType, WeakType)   \
182     ( this->GetComponentType() == WeakType )                        \
183       {                                                             \
184       using InternalByteSwapperType = itk::ByteSwapper<StrongType>; \
185       if ( m_ByteOrder == LittleEndian )                            \
186         {                                                           \
187         InternalByteSwapperType::SwapRangeFromSystemToLittleEndian( \
188           (StrongType *)buffer, this->GetImageSizeInComponents() ); \
189         }                                                           \
190       else if ( m_ByteOrder == BigEndian )                          \
191         {                                                           \
192         InternalByteSwapperType::SwapRangeFromSystemToBigEndian(    \
193           (StrongType *)buffer, this->GetImageSizeInComponents() ); \
194         }                                                           \
195       }
196
197     // Swap bytes if necessary
198     if itkReadRawBytesAfterSwappingMacro( unsigned short, USHORT )
199       else if itkReadRawBytesAfterSwappingMacro( short, SHORT )
200         else if itkReadRawBytesAfterSwappingMacro( char, CHAR )
201           else if itkReadRawBytesAfterSwappingMacro( unsigned char, UCHAR )
202             else if itkReadRawBytesAfterSwappingMacro( unsigned int, UINT )
203               else if itkReadRawBytesAfterSwappingMacro( int, INT )
204                 else if itkReadRawBytesAfterSwappingMacro( float, FLOAT )
205                   else if itkReadRawBytesAfterSwappingMacro( double, DOUBLE );
206 #endif
207   }
208 }
209
210 //--------------------------------------------------------------------
211 // Write Image Information
212 void clitk::VoxImageIO::WriteImageInformation(bool keepOfStream)
213 {
214   // Check dimension
215   if (GetNumberOfDimensions() != 3 &&  GetNumberOfDimensions() != 2) {
216     itkExceptionMacro(<<"Write failed: only 3D and 2D image for Vox file format yet.");
217   }
218
219   // Open the file
220   clitk::openFileForWriting(file, m_FileName);
221   // write magic number
222   file << "VOX v2" << std::endl;
223   // write grid size/spacing
224   file << "# Size" << std::endl;
225   file << GetDimensions(0) << " "
226        << GetDimensions(1) << " "
227        << GetDimensions(2) << std::endl;
228   file << "# Spacing" << std::endl;
229   file.precision(40);
230   file << GetSpacing(0) << " "
231        << GetSpacing(1) << " "
232        << GetSpacing(2) << std::endl;
233   file << "# Image dim" << std::endl << "3" << std::endl;
234   file << "# Image type" << std::endl;
235
236   std::string dataTypeName;
237   if (GetComponentType() == itk::ImageIOBase::CHAR) dataTypeName = "schar";
238   else if (GetComponentType() == itk::ImageIOBase::UCHAR) dataTypeName = "uchar";
239   else if (GetComponentType() == itk::ImageIOBase::SHORT) dataTypeName = "sshort";
240   else if (GetComponentType() == itk::ImageIOBase::USHORT) dataTypeName = "ushort";
241   else if (GetComponentType() == itk::ImageIOBase::INT) dataTypeName = "int";
242   else if (GetComponentType() == itk::ImageIOBase::UINT) dataTypeName = "uint";
243   else if (GetComponentType() == itk::ImageIOBase::FLOAT) dataTypeName = "float";
244   else if (GetComponentType() == itk::ImageIOBase::DOUBLE) dataTypeName = "double";
245   else {
246     itkExceptionMacro(<<"Write failed: Wanted pixel type "
247                       << "(char, uchar, short, ushort, int, uint, float, double)"
248                       << " but Vox is : " << dataTypeName);
249   }
250   file << dataTypeName << std::endl;
251
252   // close file
253   if (!keepOfStream) file.close();
254 }
255
256 //--------------------------------------------------------------------
257 // Write Image Information
258 bool clitk::VoxImageIO::CanWriteFile(const char* FileNameToWrite)
259 {
260   std::string filename(FileNameToWrite);
261   std::string filenameext = GetExtension(filename);
262   if (filenameext != std::string("vox")) return false;
263   return true;
264 }
265
266 //--------------------------------------------------------------------
267 // Write Image
268 void clitk::VoxImageIO::Write(const void * buffer)
269 {
270   clitk::VoxImageIO::WriteImageInformation(true);
271   SetByteOrderToLittleEndian();
272
273   //-------------------------------------------
274   // Cut & Paste from itkRawImageIO
275   // (warning BigEndian / LittleEndian)
276   const unsigned long numberOfBytes      = this->GetImageSizeInBytes();
277   const unsigned long numberOfComponents = this->GetImageSizeInComponents();
278 #if ( ITK_VERSION_MAJOR < 5 )
279   using namespace itk;
280   // Swap bytes if necessary
281   if itkWriteRawBytesAfterSwappingMacro( unsigned short, USHORT )
282     else if itkWriteRawBytesAfterSwappingMacro( short, SHORT )
283       else if itkWriteRawBytesAfterSwappingMacro( char, CHAR )
284         else if itkWriteRawBytesAfterSwappingMacro( unsigned char, UCHAR )
285           else if itkWriteRawBytesAfterSwappingMacro( unsigned int, UINT )
286             else if itkWriteRawBytesAfterSwappingMacro( int, INT )
287               else if itkWriteRawBytesAfterSwappingMacro( float, FLOAT )
288                 else if itkWriteRawBytesAfterSwappingMacro( double, DOUBLE );
289 #else
290 #define itkWriteRawBytesAfterSwappingMacro(StrongType, WeakType)        \
291   ( this->GetComponentType() == WeakType )                              \
292     {                                                                   \
293     using InternalByteSwapperType = itk::ByteSwapper<StrongType>;       \
294     const SizeValueType numberOfPixels = numberOfBytes/(sizeof(StrongType)); \
295     if ( m_ByteOrder == LittleEndian )                                  \
296       {                                                                 \
297       StrongType *tempBuffer = new StrongType[numberOfPixels];          \
298       memcpy((char *)tempBuffer, buffer, numberOfBytes);          \
299       InternalByteSwapperType::SwapRangeFromSystemToLittleEndian(       \
300         (StrongType *)tempBuffer, numberOfComponents);                  \
301       file.write((char *)tempBuffer, numberOfBytes);                            \
302       delete[] tempBuffer;                                              \
303       }                                                                 \
304     else if ( m_ByteOrder == BigEndian )                                \
305       {                                                                 \
306       StrongType *tempBuffer = new StrongType[numberOfPixels];          \
307       memcpy((char *)tempBuffer, buffer, numberOfBytes);          \
308       InternalByteSwapperType::SwapRangeFromSystemToBigEndian(          \
309         (StrongType *)tempBuffer, numberOfComponents);                  \
310       file.write((char *)tempBuffer, numberOfBytes);                            \
311       delete[] tempBuffer;                                              \
312       }                                                                 \
313     else                                                                \
314       {                                                                 \
315       file.write(static_cast< const char * >( buffer ), numberOfBytes); \
316       }                                                                 \
317     }
318
319     // Swap bytes if necessary
320     if itkWriteRawBytesAfterSwappingMacro(unsigned short, USHORT)
321     else if itkWriteRawBytesAfterSwappingMacro(short, SHORT)
322     else if itkWriteRawBytesAfterSwappingMacro(char, CHAR)
323     else if itkWriteRawBytesAfterSwappingMacro(unsigned char, UCHAR)
324     else if itkWriteRawBytesAfterSwappingMacro(unsigned int, UINT)
325     else if itkWriteRawBytesAfterSwappingMacro(int, INT)
326     else if itkWriteRawBytesAfterSwappingMacro(long, LONG)
327     else if itkWriteRawBytesAfterSwappingMacro(unsigned long, ULONG)
328     else if itkWriteRawBytesAfterSwappingMacro(float, FLOAT)
329     else if itkWriteRawBytesAfterSwappingMacro(double, DOUBLE)
330 #endif
331   //-------------------------------------------
332
333   file.close();
334 } ////
335
336 #endif /* end #define CLITKVOXIMAGEIO_CXX */
337