fw4spl
vtk.cpp
1 /* ***** BEGIN LICENSE BLOCK *****
2  * FW4SPL - Copyright (C) IRCAD, 2009-2018.
3  * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
4  * published by the Free Software Foundation.
5  * ****** END LICENSE BLOCK ****** */
6 #include "fwVtkIO/vtk.hpp"
7 
8 #include <fwData/Image.hpp>
9 #include <fwData/ObjectLock.hpp>
10 
11 #include <fwDataTools/helper/Image.hpp>
12 #include <fwDataTools/helper/ImageGetter.hpp>
13 
14 #include <fwMath/MeshFunctions.hpp>
15 
16 #include <boost/assign/list_of.hpp>
17 #include <boost/cast.hpp>
18 
19 #include <vtkCell.h>
20 #include <vtkCellType.h>
21 #include <vtkDataArray.h>
22 #include <vtkDataSetAttributes.h>
23 #include <vtkImageData.h>
24 #include <vtkImageExport.h>
25 #include <vtkImageImport.h>
26 #include <vtkLookupTable.h>
27 #include <vtkMatrix4x4.h>
28 #include <vtkPointData.h>
29 #include <vtkPoints.h>
30 #include <vtkPolyData.h>
31 #include <vtkPolyDataNormals.h>
32 #include <vtkPolyDataWriter.h>
33 #include <vtkSetGet.h>
34 #include <vtkSmartPointer.h>
35 #include <vtkType.h>
36 #include <vtkUnstructuredGrid.h>
37 
38 #include <cstring>
39 #include <functional>
40 #include <numeric>
41 #include <stdexcept>
42 
43 namespace fwVtkIO
44 {
45 
46 // ------------------------------------------------------------------------------
47 
48 TypeTranslator::fwToolsToVtkMap::mapped_type TypeTranslator::translate(
49  const TypeTranslator::fwToolsToVtkMap::key_type& key )
50 {
51  fwToolsToVtkMap::const_iterator it = s_toVtk.find( key );
52  FW_RAISE_IF("Unknown Type: " << key, it == s_toVtk.end() );
53  return it->second;
54 }
55 
56 // ------------------------------------------------------------------------------
57 
58 TypeTranslator::VtkTofwToolsMap::mapped_type TypeTranslator::translate(
59  const TypeTranslator::VtkTofwToolsMap::key_type& key )
60 {
61  VtkTofwToolsMap::const_iterator it = s_fromVtk.find( key );
62  FW_RAISE_IF("Unknown Type: " << key, it == s_fromVtk.end() );
63  return it->second;
64 }
65 
66 const TypeTranslator::fwToolsToVtkMap TypeTranslator::s_toVtk
67  = boost::assign::map_list_of
68  // char and signed char are treated as the same type.
69  // and plain char is used when writing an int8 image
70  ( fwTools::Type::create("int8" ), VTK_CHAR )
71  ( fwTools::Type::create("uint8" ), VTK_UNSIGNED_CHAR )
72 
73  ( fwTools::Type::create("int16"), VTK_SHORT )
74  ( fwTools::Type::create("uint16"), VTK_UNSIGNED_SHORT )
75 
76  ( fwTools::Type::create("int32"), VTK_INT )
77  ( fwTools::Type::create("uint32"), VTK_UNSIGNED_INT )
78 
79  ( fwTools::Type::create("float" ), VTK_FLOAT )
80  ( fwTools::Type::create("double"), VTK_DOUBLE )
81 
82 #if ( INT_MAX < LONG_MAX )
83  ( fwTools::Type::create("int64"), VTK_LONG )
84  ( fwTools::Type::create("uint64"), VTK_UNSIGNED_LONG )
85 #endif
86  ;
87 
88 const TypeTranslator::VtkTofwToolsMap TypeTranslator::s_fromVtk
89  = boost::assign::map_list_of
90 
91  // char and signed char are treated as the same type.
92  // and plain char is used when writing an int8 image
93  ( VTK_SIGNED_CHAR, fwTools::Type::create("int8" ) )
94  ( VTK_CHAR, fwTools::Type::create("int8" ) )
95  ( VTK_UNSIGNED_CHAR, fwTools::Type::create("uint8" ) )
96 
97  ( VTK_SHORT, fwTools::Type::create("int16") )
98  ( VTK_UNSIGNED_SHORT, fwTools::Type::create("uint16") )
99 
100  ( VTK_INT, fwTools::Type::create("int32") )
101  ( VTK_UNSIGNED_INT, fwTools::Type::create("uint32") )
102 
103  ( VTK_FLOAT, fwTools::Type::create("float" ) )
104  ( VTK_DOUBLE, fwTools::Type::create("double") )
105 
106 #if ( INT_MAX < LONG_MAX )
107  ( VTK_LONG, fwTools::Type::create("int64") )
108  ( VTK_UNSIGNED_LONG, fwTools::Type::create("uint64") )
109 
110  ( VTK___INT64, fwTools::Type::create("int64") )
111  ( VTK_LONG_LONG, fwTools::Type::create("int64") )
112 
113  ( VTK_UNSIGNED___INT64, fwTools::Type::create("uint64") )
114  ( VTK_UNSIGNED_LONG_LONG, fwTools::Type::create("uint64") )
115 #else
116  ( VTK_LONG, fwTools::Type::create("int32") )
117  ( VTK_UNSIGNED_LONG, fwTools::Type::create("uint32") )
118 #endif
119  ;
120 
121 // -----------------------------------------------------------------------------
122 
123 void toVTKImage( ::fwData::Image::csptr data, vtkImageData* dst)
124 {
125  vtkSmartPointer< vtkImageImport > importer = vtkSmartPointer< vtkImageImport >::New();
126 
127  configureVTKImageImport( importer, data );
128 
129  importer->Update();
130 
131  dst->ShallowCopy(importer->GetOutput());
132 }
133 
134 // -----------------------------------------------------------------------------
135 
136 template< typename IMAGETYPE >
137 void* newBuffer(size_t size)
138 {
139  IMAGETYPE* destBuffer;
140  try
141  {
142  destBuffer = new IMAGETYPE[ size ];
143  }
144  catch (std::exception& e)
145  {
146  OSLM_ERROR("No enough memory to allocate an image of type "
147  << fwTools::makeDynamicType<IMAGETYPE>().string()
148  << " and of size "<< size << "." << std::endl
149  << e.what() );
150  throw;
151  }
152  return destBuffer;
153 }
154 
155 // -----------------------------------------------------------------------------
156 
157 template< typename IMAGETYPE >
158 void fromRGBBuffer( void* input, size_t size, void*& destBuffer)
159 {
160  if(destBuffer == NULL)
161  {
162  destBuffer = newBuffer<IMAGETYPE>(size);
163  }
164 
165  IMAGETYPE* destBufferTyped = (IMAGETYPE*)destBuffer;
166  IMAGETYPE* inputTyped = (IMAGETYPE*)input;
167  IMAGETYPE* finalPtr = ((IMAGETYPE*)destBuffer) + size;
168  IMAGETYPE valR, valG, valB;
169 
170  while (destBufferTyped < finalPtr)
171  {
172  valR = (IMAGETYPE)(float((*(inputTyped++)) * 0.30));
173  valG = (IMAGETYPE)(float((*(inputTyped++)) * 0.59));
174  valB = (IMAGETYPE)(float((*(inputTyped++)) * 0.11));
175  (*destBufferTyped++) = valR + valG + valB;
176  }
177 }
178 
179 // -----------------------------------------------------------------------------
180 
181 template< typename IMAGETYPE >
182 void fromRGBBufferColor( void* input, size_t size, void*& destBuffer)
183 {
184  if(destBuffer == NULL)
185  {
186  destBuffer = newBuffer<IMAGETYPE>(size);
187  }
188 
189  IMAGETYPE* destBufferTyped = (IMAGETYPE*)destBuffer;
190  IMAGETYPE* inputTyped = (IMAGETYPE*)input;
191  IMAGETYPE* finalPtr = ((IMAGETYPE*)destBuffer) + size;
192 
193  while (destBufferTyped < finalPtr)
194  {
195  (*destBufferTyped++) = (*(inputTyped++));
196  }
197 }
198 
199 // -----------------------------------------------------------------------------
200 
201 void fromVTKImage( vtkImageData* source, ::fwData::Image::sptr destination )
202 {
203  SLM_ASSERT("vtkImageData source and/or ::fwData::Image destination are not correct", destination && source );
204 
205  ::fwDataTools::helper::Image imageHelper(destination);
206 
207  // ensure image size correct
208 // source->UpdateInformation();
209 // source->PropagateUpdateExtent();
210 
211  int dim = source->GetDataDimension();
212  OSLM_TRACE("source->GetDataDimension() : " << dim);
213 
214  if(dim == 2)
215  {
216  int size[2];
217  size[0] = source->GetDimensions()[0];
218  size[1] = source->GetDimensions()[1];
219  destination->setSize( ::fwData::Image::SizeType(size, size+dim) );
220 
221  double spacing[2];
222  spacing[0] = source->GetSpacing()[0];
223  spacing[1] = source->GetSpacing()[1];
224  destination->setSpacing( ::fwData::Image::SpacingType(spacing, spacing+dim) );
225 
226  double origin[2];
227  origin[0] = source->GetOrigin()[0];
228  origin[1] = source->GetOrigin()[1];
229  destination->setOrigin( ::fwData::Image::OriginType(origin, origin+dim) );
230  }
231  else
232  {
233  destination->setSize( ::fwData::Image::SizeType(source->GetDimensions(), source->GetDimensions()+dim) );
234  destination->setSpacing( ::fwData::Image::SpacingType(source->GetSpacing(), source->GetSpacing()+dim) );
235  destination->setOrigin( ::fwData::Image::OriginType(source->GetOrigin(), source->GetOrigin()+dim) );
236  }
237 
238  const int nbComponents = source->GetNumberOfScalarComponents();
239  const size_t size =
240  std::accumulate(source->GetDimensions(), source->GetDimensions()+dim, std::max(3,
241  nbComponents),
242  std::multiplies<size_t>() );
243  const void* input = source->GetScalarPointer();
244 
245  if (size != 0)
246  {
247  void* destBuffer;
248  const int nbBytePerPixel = source->GetScalarSize();
249  OSLM_TRACE("image size : " << size << " - nbBytePerPixel : " << nbBytePerPixel );
250 
251  OSLM_TRACE(nbComponents << " components, " << TypeTranslator::translate( source->GetScalarType() ));
252  destination->setType( TypeTranslator::translate( source->GetScalarType() ) );
253  destination->setNumberOfComponents(nbComponents);
254  destination->allocate();
255  ::fwData::ObjectLock lock(destination);
256  destBuffer = imageHelper.getBuffer();
257  const size_t sizeInBytes = destination->getSizeInBytes();
258  std::memcpy(destBuffer, input, sizeInBytes);
259 
260  }
261 
262 }
263 
264 // ------------------------------------------------------------------------------
265 
266 void configureVTKImageImport( ::vtkImageImport* _pImageImport, ::fwData::Image::csptr _pDataImage )
267 {
268  ::fwDataTools::helper::ImageGetter imageHelper(_pDataImage);
269 
270  if(_pDataImage->getSize().size() == 2)
271  {
272  _pImageImport->SetDataSpacing( _pDataImage->getSpacing().at(0),
273  _pDataImage->getSpacing().at(1),
274  0
275  );
276 
277  _pImageImport->SetDataOrigin( _pDataImage->getOrigin().at(0),
278  _pDataImage->getOrigin().at(1),
279  0
280  );
281 
282  _pImageImport->SetWholeExtent( 0, _pDataImage->getSize().at(0) - 1,
283  0, _pDataImage->getSize().at(1) - 1,
284  0, 0
285  );
286  }
287  else
288  {
289  _pImageImport->SetDataSpacing( _pDataImage->getSpacing().at(0),
290  _pDataImage->getSpacing().at(1),
291  _pDataImage->getSpacing().at(2)
292  );
293 
294  _pImageImport->SetDataOrigin( _pDataImage->getOrigin().at(0),
295  _pDataImage->getOrigin().at(1),
296  _pDataImage->getOrigin().at(2)
297  );
298 
299  _pImageImport->SetWholeExtent( 0, _pDataImage->getSize().at(0) - 1,
300  0, _pDataImage->getSize().at(1) - 1,
301  0, _pDataImage->getSize().at(2) - 1
302  );
303  }
304 
305  _pImageImport->SetNumberOfScalarComponents(static_cast<int>( _pDataImage->getNumberOfComponents() ));
306 
307  // copy WholeExtent to DataExtent
308  _pImageImport->SetDataExtentToWholeExtent();
309  // no copy, no buffer destruction/management
310  _pImageImport->SetImportVoidPointer( imageHelper.getBuffer() );
311  // used to set correct pixeltype to VtkImage
312  _pImageImport->SetDataScalarType( TypeTranslator::translate(_pDataImage->getType()) );
313 }
314 
315 // -----------------------------------------------------------------------------
316 
317 vtkSmartPointer<vtkMatrix4x4> toVTKMatrix( ::fwData::TransformationMatrix3D::csptr _transfoMatrix )
318 {
319  auto matrix = vtkSmartPointer<vtkMatrix4x4>::New();
320  for(std::uint8_t l = 0; l < 4; l++)
321  {
322  for(std::uint8_t c = 0; c < 4; c++)
323  {
324  matrix->SetElement(l, c, _transfoMatrix->getCoefficient(l, c));
325  }
326  }
327  return matrix;
328 }
329 
330 // -----------------------------------------------------------------------------
331 
332 bool fromVTKMatrix( vtkMatrix4x4* _matrix, ::fwData::TransformationMatrix3D::sptr _transfoMatrix)
333 {
334  bool res = true;
335  for(std::uint8_t l = 0; l < 4; l++)
336  {
337  for(std::uint8_t c = 0; c < 4; c++)
338  {
339  _transfoMatrix->setCoefficient(l, c, _matrix->GetElement(l, c));
340  }
341  }
342  return res;
343 }
344 
345 // -----------------------------------------------------------------------------
346 
347 } // namespace fwVtkIO
#define OSLM_TRACE(message)
Definition: spyLog.hpp:230
Defines an helper to modify an fwData::Image by adding few medical fields and create in parallel the ...
#define OSLM_ERROR(message)
Definition: spyLog.hpp:274
#define SLM_ASSERT(message, cond)
work like &#39;assert&#39; from &#39;cassert&#39;, with in addition a message logged by spylog (with FATAL loglevel) ...
Definition: spyLog.hpp:308
Defines an helper to modify an fwData::Image by adding few medical fields and create in parallel the ...
Definition: ImageGetter.hpp:23
std::vector< double > SpacingType
Image spacing type.
A simple helper to lock specific object, manages : Image, Mesh and Array.
Definition: ObjectLock.hpp:26
::fwData::Array::SizeType SizeType
Image size type.
std::vector< double > OriginType
Image origin type.