]> Creatis software - clitk.git/blob - common/rtkImagXImageIO.cxx
With ITK 5, add itkReadRawBytesAfterSwappingMacro and itkWriteRawBytesAfterSwappingMacro
[clitk.git] / common / rtkImagXImageIO.cxx
1 /*=========================================================================
2  *
3  *  Copyright RTK Consortium
4  *
5  *  Licensed under the Apache License, Version 2.0 (the "License");
6  *  you may not use this file except in compliance with the License.
7  *  You may obtain a copy of the License at
8  *
9  *         http://www.apache.org/licenses/LICENSE-2.0.txt
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  *
17  *=========================================================================*/
18
19 #include "rtkImagXImageIO.h"
20 #include "rtkImagXXMLFileReader.h"
21
22 // itk include (for itkReadRawBytesAfterSwappingMacro)
23 #include <itkRawImageIO.h>
24 #include <itksys/SystemTools.hxx>
25 #include <itkMetaDataObject.h>
26 #include <itkMatrix.h>
27
28 //--------------------------------------------------------------------
29 // Read Image Information
30 void rtk::ImagXImageIO::ReadImageInformation()
31 {
32   rtk::ImagXXMLFileReader::Pointer xmlReader;
33
34   xmlReader = rtk::ImagXXMLFileReader::New();
35   xmlReader->SetFilename(m_FileName);
36   xmlReader->GenerateOutputInformation();
37
38   itk::MetaDataDictionary &dic = *(xmlReader->GetOutputObject() );
39
40   typedef itk::MetaDataObject< double >      MetaDataDoubleType;
41   typedef itk::MetaDataObject< std::string > MetaDataStringType;
42   typedef itk::MetaDataObject< int >         MetaDataIntType;
43
44   std::string pixelType = dynamic_cast<MetaDataStringType*>(dic["pixelFormat"].GetPointer() )->GetMetaDataObjectValue();
45   if(pixelType=="Type_uint8")
46     SetComponentType(itk::ImageIOBase::UCHAR);
47   if(pixelType=="Type_sint8")
48     SetComponentType(itk::ImageIOBase::CHAR);
49   if(pixelType=="Type_uint16")
50     SetComponentType(itk::ImageIOBase::USHORT);
51   if(pixelType=="Type_sint16")
52     SetComponentType(itk::ImageIOBase::SHORT);
53   if(pixelType=="Type_uint32")
54     SetComponentType(itk::ImageIOBase::UINT);
55   if(pixelType=="Type_sint32")
56     SetComponentType(itk::ImageIOBase::INT);
57   if(pixelType=="Type_float")
58     SetComponentType(itk::ImageIOBase::FLOAT);
59
60   if( dic["dimensions"].GetPointer() == NULL )
61     SetNumberOfDimensions(3);
62   else
63     SetNumberOfDimensions( ( dynamic_cast<MetaDataIntType *>(dic["dimensions"].GetPointer() )->GetMetaDataObjectValue() ) );
64
65   SetDimensions(0, dynamic_cast<MetaDataIntType *>(dic["x"].GetPointer() )->GetMetaDataObjectValue() );
66   SetSpacing(0, dynamic_cast<MetaDataDoubleType *>(dic["spacing_x"].GetPointer() )->GetMetaDataObjectValue() );
67   if(GetNumberOfDimensions()>1)
68     {
69     SetDimensions(1, dynamic_cast<MetaDataIntType *>(dic["y"].GetPointer() )->GetMetaDataObjectValue() );
70     SetSpacing(1, dynamic_cast<MetaDataDoubleType *>(dic["spacing_y"].GetPointer() )->GetMetaDataObjectValue() );
71     }
72   if(GetNumberOfDimensions()>2)
73     {
74     SetDimensions(2, dynamic_cast<MetaDataIntType *>(dic["z"].GetPointer() )->GetMetaDataObjectValue() );
75     SetSpacing(2, dynamic_cast<MetaDataDoubleType *>(dic["spacing_z"].GetPointer() )->GetMetaDataObjectValue() );
76     if(GetSpacing(2) == 0)
77       SetSpacing(2, 1);
78     }
79
80   itk::Matrix<double, 4, 4> matrix;
81   if(dic["matrixTransform"].GetPointer() == NULL)
82     matrix.SetIdentity();
83   else
84     {
85     std::istringstream iss(
86       dynamic_cast<MetaDataStringType*>(dic["matrixTransform"].GetPointer() )->GetMetaDataObjectValue() );
87     for(unsigned int j=0; j<4; j++)
88       for(unsigned int i=0; i<4; i++)
89         iss >> matrix[j][i];
90     matrix /= matrix[3][3];
91     }
92
93   std::vector<double> direction;
94   for(unsigned int i=0; i<GetNumberOfDimensions(); i++)
95     {
96     direction.clear();
97     for(unsigned int j=0; j<GetNumberOfDimensions(); j++)
98       direction.push_back(matrix[i][j]);
99     SetDirection(i, direction);
100     SetOrigin(i, matrix[i][3]);
101     }
102
103   if(std::string("LSB") == dynamic_cast<MetaDataStringType*>(dic["byteOrder"].GetPointer() )->GetMetaDataObjectValue() )
104     this->SetByteOrder(LittleEndian);
105   else
106     this->SetByteOrder(BigEndian);
107
108   // Prepare raw file name
109   m_RawFileName = itksys::SystemTools::GetFilenamePath(m_FileName);
110   if(m_RawFileName != "")
111     m_RawFileName += std::string("/");
112   m_RawFileName += dynamic_cast<MetaDataStringType*>(dic["rawFile"].GetPointer() )->GetMetaDataObjectValue();
113 } ////
114
115 //--------------------------------------------------------------------
116 // Read Image Information
117 bool rtk::ImagXImageIO::CanReadFile(const char* FileNameToRead)
118 {
119   std::string ext = itksys::SystemTools::GetFilenameLastExtension(FileNameToRead);
120
121   if( ext!=std::string(".xml") )
122     return false;
123
124   std::ifstream is(FileNameToRead);
125   if(!is.is_open() )
126     return false;
127
128   // If the XML file has "<image name=" at the beginning of the first or second
129   // line, we assume this is an ImagX file
130   std::string line;
131
132   std::getline(is, line);
133   if(line.substr(0, 12) == std::string("<image name=") )
134     return true;
135
136   std::getline(is, line);
137   if(line.substr(0, 12) == std::string("<image name=") )
138     return true;
139
140   return false;
141 } ////
142
143 //--------------------------------------------------------------------
144 // Read Image Content
145 void rtk::ImagXImageIO::Read(void * buffer)
146 {
147   // Adapted from itkRawImageIO
148   std::ifstream is(m_RawFileName.c_str(), std::ios::binary);
149
150   if(!is.is_open() )
151     itkExceptionMacro(<<"Could not open file " << m_RawFileName);
152
153   unsigned long numberOfBytesToBeRead = GetComponentSize();
154   for(unsigned int i=0; i<GetNumberOfDimensions(); i++) numberOfBytesToBeRead *= GetDimensions(i);
155
156   if(!this->ReadBufferAsBinary(is, buffer, numberOfBytesToBeRead) ) {
157     itkExceptionMacro(<<"Read failed: Wanted "
158                       << numberOfBytesToBeRead
159                       << " bytes, but read "
160                       << is.gcount() << " bytes.");
161     }
162   itkDebugMacro(<< "Reading Done");
163
164   // Adapted from itkRawImageIO
165     {
166 #if ( ITK_VERSION_MAJOR < 5 )
167     using namespace itk;
168     // Swap bytes if necessary
169     if itkReadRawBytesAfterSwappingMacro( unsigned short, USHORT )
170     else if itkReadRawBytesAfterSwappingMacro( short, SHORT )
171     else if itkReadRawBytesAfterSwappingMacro( char, CHAR )
172     else if itkReadRawBytesAfterSwappingMacro( unsigned char, UCHAR )
173     else if itkReadRawBytesAfterSwappingMacro( unsigned int, UINT )
174     else if itkReadRawBytesAfterSwappingMacro( int, INT )
175     else if itkReadRawBytesAfterSwappingMacro( float, FLOAT )
176     else if itkReadRawBytesAfterSwappingMacro( double, DOUBLE );
177 #else
178   #define itkReadRawBytesAfterSwappingMacro(StrongType, WeakType)   \
179     ( this->GetComponentType() == WeakType )                        \
180       {                                                             \
181       using InternalByteSwapperType = itk::ByteSwapper<StrongType>; \
182       if ( m_ByteOrder == LittleEndian )                            \
183         {                                                           \
184         InternalByteSwapperType::SwapRangeFromSystemToLittleEndian( \
185           (StrongType *)buffer, this->GetImageSizeInComponents() ); \
186         }                                                           \
187       else if ( m_ByteOrder == BigEndian )                          \
188         {                                                           \
189         InternalByteSwapperType::SwapRangeFromSystemToBigEndian(    \
190           (StrongType *)buffer, this->GetImageSizeInComponents() ); \
191         }                                                           \
192       }
193
194     // Swap bytes if necessary
195     if itkReadRawBytesAfterSwappingMacro( unsigned short, USHORT )
196     else if itkReadRawBytesAfterSwappingMacro( short, SHORT )
197     else if itkReadRawBytesAfterSwappingMacro( char, CHAR )
198     else if itkReadRawBytesAfterSwappingMacro( unsigned char, UCHAR )
199     else if itkReadRawBytesAfterSwappingMacro( unsigned int, UINT )
200     else if itkReadRawBytesAfterSwappingMacro( int, INT )
201     else if itkReadRawBytesAfterSwappingMacro( float, FLOAT )
202     else if itkReadRawBytesAfterSwappingMacro( double, DOUBLE );
203 #endif
204     }
205 }
206
207 //--------------------------------------------------------------------
208 // Write Image Information
209 void rtk::ImagXImageIO::WriteImageInformation( bool itkNotUsed(keepOfStream) )
210 {
211 }
212
213 //--------------------------------------------------------------------
214 // Write Image Information
215 bool rtk::ImagXImageIO::CanWriteFile( const char* itkNotUsed(FileNameToWrite) )
216 {
217   return false;
218 }
219
220 //--------------------------------------------------------------------
221 // Write Image
222 void rtk::ImagXImageIO::Write( const void * itkNotUsed(buffer) )
223 {
224 } ////