SMIL  0.9.1
DImageIO_VTK.hpp
1 /*
2  * Copyright (c) 2011-2016, Matthieu FAESSEL and ARMINES
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of Matthieu FAESSEL, or ARMINES nor the
14  * names of its contributors may be used to endorse or promote products
15  * derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 
30 #ifndef _D_IMAGE_IO_VTK_HPP
31 #define _D_IMAGE_IO_VTK_HPP
32 
33 
34 #include <fstream>
35 #include <cstdlib>
36 #include <string>
37 #include <cctype>
38 
39 #include "Core/include/private/DTypes.hpp"
40 #include "Core/include/private/DImage.hpp"
41 #include "IO/include/private/DImageIO.hpp"
42 
43 using namespace std;
44 
45 
46 namespace smil
47 {
53  struct VTKHeader
54  {
55  VTKHeader()
56  : width(0), height(0), depth(0),
57  pointNbr(0), scalarType(ImageFileInfo::SCALAR_TYPE_UNKNOWN),
58  scalarCoeff(0), binaryFile(false), startPos(0)
59  {
60  }
61 
62  UINT width, height, depth;
63  UINT pointNbr;
64  ImageFileInfo::ScalarType scalarType;
65  string scalarTypeStr;
66  double scalarCoeff;
67  bool binaryFile;
68  streampos startPos;
69  };
70 
71  // Big/Little endian swap
72  template <class T>
73  void endswap(T *objp)
74  {
75  unsigned char *memp = reinterpret_cast<unsigned char*>(objp);
76  std::reverse(memp, memp + sizeof(T));
77  }
78 
79  RES_T readVTKHeader(ifstream &fp, VTKHeader &hStruct);
80  RES_T getVTKFileInfo(const char* filename, ImageFileInfo &fInfo);
81 
82  template <class T=void>
84  {
85  public:
87  : ImageFileHandler<T>("BMP"),
88  littleEndian(false),
89  writeBinary(true)
90  {
91  }
92 
93  bool littleEndian;
94 
95  virtual RES_T getFileInfo(const char* filename, ImageFileInfo &fInfo)
96  {
97  std::ifstream fp;
98 
99  /* open image file */
100  fp.open(filename, ios_base::binary);
101 
102  // fp.open(filename);
103  if (!fp)
104  {
105  cerr << "error: couldn't open " << filename << "!" << endl;
106  return RES_ERR;
107  }
108 
109  VTKHeader hStruct;
110  if (readVTKHeader(fp, hStruct)!=RES_OK)
111  {
112  fp.close();
113  ERR_MSG("Error reading VTK file header");
114  return RES_ERR;
115  }
116 
117  fInfo.width = hStruct.width;
118  fInfo.height = hStruct.height;
119  fInfo.depth = hStruct.depth;
120  fInfo.colorType = ImageFileInfo::COLOR_TYPE_GRAY;
121  fInfo.scalarType = hStruct.scalarType;
122 
123  fp.close();
124 
125  return RES_OK;
126  }
127 
128  bool writeBinary;
129 
130  virtual RES_T read(const char* filename, Image<T> &image)
131  {
132  std::ifstream fp;
133 
134  /* open image file */
135  fp.open(filename, ios_base::binary);
136 
137  // fp.open(filename);
138  if (!fp)
139  {
140  cerr << "error: couldn't open " << filename << "!" << endl;
141  return RES_ERR;
142  }
143 
144  VTKHeader hStruct;
145  if (readVTKHeader(fp, hStruct)!=RES_OK)
146  {
147  fp.close();
148  ERR_MSG("Error reading VTK file header");
149  return RES_ERR;
150  }
151 
152  ImageFileInfo::ScalarType scalarType = hStruct.scalarType==ImageFileInfo::SCALAR_TYPE_UNKNOWN ? ImageFileInfo::SCALAR_TYPE_UINT8 : hStruct.scalarType; // default, if not specified in the file header
153 
154  if ( (typeid(T)==typeid(unsigned char) && scalarType!=ImageFileInfo::SCALAR_TYPE_UINT8)
155  || (typeid(T)==typeid(unsigned short) && scalarType!=ImageFileInfo::SCALAR_TYPE_UINT16)
156  || (typeid(T)==typeid(short) && scalarType!=ImageFileInfo::SCALAR_TYPE_INT16))
157  {
158  cout << "Error: input file type is " << hStruct.scalarTypeStr << endl;
159  fp.close();
160  return RES_ERR_IO;
161  }
162 
163  int width = hStruct.width, height = hStruct.height, depth = hStruct.depth;
164  image.setSize(width, height, depth);
165  typename Image<T>::volType slices = image.getSlices();
166  typename Image<T>::sliceType curSlice;
167  typename Image<T>::lineType curLine;
168 
169  // Return to the begining of the data
170  fp.seekg(hStruct.startPos);
171 
172  double scalarCoeff = double(ImDtTypes<T>::max()) / hStruct.scalarCoeff;
173 
174  if (!hStruct.binaryFile)
175  {
176  double val;
177  for (int z=0;z<depth;z++)
178  {
179  curSlice = slices[z];
180  for (int y=height-1;y>=0;y--)
181  {
182  curLine = curSlice[y];
183  for (int x=0;x<width;x++)
184  {
185  fp >> val;
186  curLine[x] = static_cast<T>(val*scalarCoeff);
187  }
188  }
189  }
190  }
191 
192  else
193  {
194  // In binary version, values are written as chars
195 
196  for (int z=0;z<depth;z++)
197  {
198  curSlice = slices[z];
199  for (int y=height-1;y>=0;y--)
200  {
201  curLine = curSlice[y];
202 
203  if (littleEndian || sizeof(T)==1)
204  fp.read((char*)curLine, sizeof(T)*width);
205  else
206  {
207  T val;
208  for (int i=0;i<width;i++)
209  {
210  fp.read((char*)&val, sizeof(T));
211  endswap(&val);
212  curLine[i] = val;
213  }
214  }
215  }
216  }
217  }
218 
219  fp.close();
220 
221  image.modified();
222 
223  return RES_OK;
224  }
225  virtual RES_T write(const Image<T> &image, const char* filename)
226  {
227  std::ofstream fp;
228 
229  /* open image file */
230  fp.open(filename, ios_base::binary);
231  if (!fp)
232  {
233  cerr << "error: couldn't open " << filename << "!" << endl;
234  return RES_ERR;
235  }
236 
237  size_t width = image.getWidth();
238  size_t height = image.getHeight();
239  size_t depth = image.getDepth();
240  size_t pixNbr = width*height*depth;
241 
242  fp << "# vtk DataFile Version 3.0" << endl;
243  fp << "vtk output" << endl;
244  fp << "BINARY" << endl;
245  fp << "DATASET STRUCTURED_POINTS" << endl;
246  fp << "DIMENSIONS " << width << " " << height << " " << depth << endl;
247  fp << "SPACING 1.0 1.0 1.0" << endl;
248  fp << "ORIGIN 0 0 0" << endl;
249  fp << "POINT_DATA " << pixNbr << endl;
250  fp << "SCALARS scalars ";
251  if (typeid(T)==typeid(unsigned char))
252  fp << "unsigned_char";
253  else if (typeid(T)==typeid(unsigned short))
254  fp << "unsigned_short";
255  fp << endl;
256 
257  if (writeBinary)
258  fp << "LOOKUP_TABLE default" << endl;
259  else
260  {
261  cerr << "not implemented (todo..)" << endl;
262  }
263 
264  typename Image<T>::volType slices = image.getSlices();
265  typename Image<T>::sliceType curSlice;
266  typename Image<T>::lineType curLine;
267 
268  if (writeBinary)
269  {
270  // todo : make this generic
271 // fp.write((char*)pixels, sizeof(T)*pixNbr);
272 
273  for (size_t z=0;z<depth;z++)
274  {
275  curSlice = slices[z];
276  for (int y=height-1;y>=0;y--)
277  {
278  curLine = curSlice[y];
279  if (littleEndian || sizeof(T)==1)
280  fp.write((char*)curLine, sizeof(T)*width);
281  else
282  {
283  T val;
284  for (size_t i=0;i<width;i++)
285  {
286  val = curLine[i];
287  endswap(&val);
288  fp.write((char*)&val, sizeof(T));
289  }
290  }
291  }
292  }
293  }
294 
295  fp.close();
296 
297  return RES_OK;
298  }
299  };
300 
301  template <>
302  inline RES_T VTKImageFileHandler<void>::read(const char *, Image<void> &)
303  {
304  return RES_ERR;
305  }
306 
307  template <>
308  inline RES_T VTKImageFileHandler<void>::write(const Image<void> &, const char *)
309  {
310  return RES_ERR;
311  }
312 
313  template <>
314  inline RES_T VTKImageFileHandler<RGB>::read(const char *, Image<RGB> &)
315  {
316  return RES_ERR_NOT_IMPLEMENTED;
317  }
318  template <>
319  inline RES_T VTKImageFileHandler<RGB>::write(const Image<RGB> &, const char *)
320  {
321  return RES_ERR_NOT_IMPLEMENTED;
322  }
323 
326 } // namespace smil
327 
328 
329 #endif // _D_IMAGE_IO_VTK_HPP
Definition: DColorConvert.h:38
Definition: DImageIO_VTK.hpp:83
virtual RES_T setSize(size_t w, size_t h, size_t d=1, bool doAllocate=true)
Set the size of image.
Definition: DImage.hxx:319
Definition: DImageIO.hpp:51
size_t getHeight() const
Get image height.
Definition: DBaseImage.h:91
virtual void modified()
Trigger modified event (allows to force display update)
Definition: DImage.hxx:223
size_t getWidth() const
Get image width.
Definition: DBaseImage.h:87
Definition: DImageIO_VTK.hpp:53
Definition: DTypes.hpp:78
Main Image class.
Definition: DQVtkViewer.hpp:44
volType getSlices() const
Get an array containing the start offset of each slice.
Definition: DImage.hpp:118
size_t getDepth() const
Get image depth (Z)
Definition: DBaseImage.h:95
RES_T read(const char *filename, Image< T > &image)
Read image file.
Definition: DImageIO.hxx:112
RES_T write(const Image< T > &image, const char *filename)
Write image file.
Definition: DImageIO.hxx:192
Definition: DCommonIO.h:70