1 /*=========================================================================
2 Program: vv http://www.creatis.insa-lyon.fr/rio/vv
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
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.
13 It is distributed under dual licence
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
21 -------------------------------------------------
22 * @file clitkVoxImageIO.cxx
23 * @author David Sarrut <david.sarrut@creatis.insa-lyon.fr>
24 * @date 17 May 2006 08:03:07
29 -------------------------------------------------*/
32 #include "clitkVoxImageIO.h"
33 #include "clitkCommon.h"
35 // itk include (for itkReadRawBytesAfterSwappingMacro)
36 #if ( ITK_VERSION_MAJOR < 5 )
37 #include "itkRawImageIO.h"
39 #include <itkByteSwapper.h>
42 //--------------------------------------------------------------------
43 // Read Image Information
44 void clitk::VoxImageIO::ReadImageInformation()
48 clitk::openFileForReading(is, m_FileName);
54 itkExceptionMacro(<<"read magic number '" << mn << "' while expect VOX");
56 // read vox file version
61 itkExceptionMacro(<<"read old format '" << mn << "'. TODO");
64 // ONLY 3D IMAGES YET ...
66 // read grid size/spacing
67 itk::Vector<unsigned int,3> dim;
68 itk::Vector<double,3> spacing;
69 itk::Vector<double,3> origin;
84 if (d != 3 && d != 2) {
85 itkExceptionMacro(<<"could not read no " << d << "D image (only 2D and 3D). TODO");
89 std::string dataTypeName;
94 m_HeaderSize = is.tellg();
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]);
106 // set other information
107 SetByteOrderToLittleEndian();
108 SetPixelType(itk::ImageIOBase::SCALAR);
109 SetNumberOfComponents(1);
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);
122 itkExceptionMacro(<<"Read failed: Wanted pixel type "
123 << "(char, uchar, short, ushort, int, uint, float, double)"
124 << " but read " << dataTypeName);
129 //--------------------------------------------------------------------
130 // Read Image Information
131 bool clitk::VoxImageIO::CanReadFile(const char* FileNameToRead)
133 std::string filename(FileNameToRead);
134 std::string filenameext = GetExtension(filename);
135 if (filenameext != std::string("vox")) return false;
139 //--------------------------------------------------------------------
140 // Read Image Content
141 void clitk::VoxImageIO::Read(void * buffer)
143 // Adapted from itkRawImageIO
146 openFileForReading(file, m_FileName);
149 unsigned long streamStart = m_HeaderSize;
150 file.seekg((long)streamStart, std::ios::beg);
152 itkExceptionMacro(<<"File seek failed (Vox Read)");
155 unsigned long numberOfBytesToBeRead = GetComponentSize();
156 for(unsigned int i=0; i<GetNumberOfDimensions(); i++) numberOfBytesToBeRead *= GetDimensions(i);
158 //DD(numberOfBytesToBeRead);
160 if(!this->ReadBufferAsBinary(file, buffer, numberOfBytesToBeRead)) {
161 itkExceptionMacro(<<"Read failed: Wanted "
162 << numberOfBytesToBeRead
163 << " bytes, but read "
164 << file.gcount() << " bytes.");
166 itkDebugMacro(<< "Reading Done");
169 #if ( ITK_VERSION_MAJOR < 5 )
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 );
181 #define itkReadRawBytesAfterSwappingMacro(StrongType, WeakType) \
182 ( this->GetComponentType() == WeakType ) \
184 using InternalByteSwapperType = itk::ByteSwapper<StrongType>; \
185 if ( m_ByteOrder == LittleEndian ) \
187 InternalByteSwapperType::SwapRangeFromSystemToLittleEndian( \
188 (StrongType *)buffer, this->GetImageSizeInComponents() ); \
190 else if ( m_ByteOrder == BigEndian ) \
192 InternalByteSwapperType::SwapRangeFromSystemToBigEndian( \
193 (StrongType *)buffer, this->GetImageSizeInComponents() ); \
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 );
210 //--------------------------------------------------------------------
211 // Write Image Information
212 void clitk::VoxImageIO::WriteImageInformation(bool keepOfStream)
215 if (GetNumberOfDimensions() != 3 && GetNumberOfDimensions() != 2) {
216 itkExceptionMacro(<<"Write failed: only 3D and 2D image for Vox file format yet.");
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;
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;
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";
246 itkExceptionMacro(<<"Write failed: Wanted pixel type "
247 << "(char, uchar, short, ushort, int, uint, float, double)"
248 << " but Vox is : " << dataTypeName);
250 file << dataTypeName << std::endl;
253 if (!keepOfStream) file.close();
256 //--------------------------------------------------------------------
257 // Write Image Information
258 bool clitk::VoxImageIO::CanWriteFile(const char* FileNameToWrite)
260 std::string filename(FileNameToWrite);
261 std::string filenameext = GetExtension(filename);
262 if (filenameext != std::string("vox")) return false;
266 //--------------------------------------------------------------------
268 void clitk::VoxImageIO::Write(const void * buffer)
270 clitk::VoxImageIO::WriteImageInformation(true);
271 SetByteOrderToLittleEndian();
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 )
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 );
290 #define itkWriteRawBytesAfterSwappingMacro(StrongType, WeakType) \
291 ( this->GetComponentType() == WeakType ) \
293 using InternalByteSwapperType = itk::ByteSwapper<StrongType>; \
294 const SizeValueType numberOfPixels = numberOfBytes/(sizeof(StrongType)); \
295 if ( m_ByteOrder == LittleEndian ) \
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; \
304 else if ( m_ByteOrder == BigEndian ) \
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; \
315 file.write(static_cast< const char * >( buffer ), numberOfBytes); \
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)
331 //-------------------------------------------
336 #endif /* end #define CLITKVOXIMAGEIO_CXX */