Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkVtkImageOverwrite.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
17 /*=========================================================================
18 
19  Program: Visualization Toolkit
20  Module: mitkVtkImageOverwrite.cpp
21 
22  Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
23  All rights reserved.
24  See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
25 
26  This software is distributed WITHOUT ANY WARRANTY; without even
27  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
28  PURPOSE. See the above copyright notice for more information.
29 
30 =========================================================================*/
31 #include "mitkVtkImageOverwrite.h"
32 
33 #include "vtkDataSetAttributes.h"
34 #include "vtkGarbageCollector.h"
35 #include "vtkImageData.h"
36 #include "vtkImageStencilData.h"
37 #include "vtkInformation.h"
38 #include "vtkInformationVector.h"
39 #include "vtkMath.h"
40 #include "vtkObjectFactory.h"
41 #include "vtkStreamingDemandDrivenPipeline.h"
42 #include "vtkTransform.h"
43 
44 #include "vtkTemplateAliasMacro.h"
45 // turn off 64-bit ints when templating over all types
46 #undef VTK_USE_INT64
47 #define VTK_USE_INT64 0
48 #undef VTK_USE_UINT64
49 #define VTK_USE_UINT64 0
50 
51 #include <float.h>
52 #include <limits.h>
53 #include <math.h>
54 
56 
57 //--------------------------------------------------------------------------
58 // The 'floor' function on x86 and mips is many times slower than these
59 // and is used a lot in this code, optimize for different CPU architectures
60 template <class F>
61 inline int vtkResliceFloor(double x, F &f)
62 {
63 #if defined mips || defined sparc || defined __ppc__
64  x += 2147483648.0;
65  unsigned int i = static_cast<unsigned int>(x);
66  f = x - i;
67  return static_cast<int>(i - 2147483648U);
68 #elif defined i386 || defined _M_IX86
69  union {
70  double d;
71  unsigned short s[4];
72  unsigned int i[2];
73  } dual;
74  dual.d = x + 103079215104.0; // (2**(52-16))*1.5
75  f = dual.s[0] * 0.0000152587890625; // 2**(-16)
76  return static_cast<int>((dual.i[1] << 16) | ((dual.i[0]) >> 16));
77 #elif defined ia64 || defined __ia64__ || defined IA64
78  x += 103079215104.0;
79  long long i = static_cast<long long>(x);
80  f = x - i;
81  return static_cast<int>(i - 103079215104LL);
82 #else
83  double y = floor(x);
84  f = x - y;
85  return static_cast<int>(y);
86 #endif
87 }
88 
89 inline int vtkResliceRound(double x)
90 {
91 #if defined mips || defined sparc || defined __ppc__
92  return static_cast<int>(static_cast<unsigned int>(x + 2147483648.5) - 2147483648U);
93 #elif defined i386 || defined _M_IX86
94  union {
95  double d;
96  unsigned int i[2];
97  } dual;
98  dual.d = x + 103079215104.5; // (2**(52-16))*1.5
99  return static_cast<int>((dual.i[1] << 16) | ((dual.i[0]) >> 16));
100 #elif defined ia64 || defined __ia64__ || defined IA64
101  x += 103079215104.5;
102  long long i = static_cast<long long>(x);
103  return static_cast<int>(i - 103079215104LL);
104 #else
105  return static_cast<int>(floor(x + 0.5));
106 #endif
107 }
108 
109 //----------------------------------------------------------------------------
111 {
112  m_Overwrite_Mode = false;
113  this->GetOutput()->AllocateScalars(VTK_UNSIGNED_INT, 1); // VTK6_TODO where should the image be allocated?
114 }
115 
116 //----------------------------------------------------------------------------
118 {
119 }
120 
121 //----------------------------------------------------------------------------
122 // constants for different boundary-handling modes
123 
124 #define VTK_RESLICE_BACKGROUND 0 // use background if out-of-bounds
125 #define VTK_RESLICE_WRAP 1 // wrap to opposite side of image
126 #define VTK_RESLICE_MIRROR 2 // mirror off of the boundary
127 #define VTK_RESLICE_BORDER 3 // use a half-voxel border
128 #define VTK_RESLICE_NULL 4 // do nothing to *outPtr if out-of-bounds
129 
130 //----------------------------------------------------------------------------
131 // rounding functions for each type, where 'F' is a floating-point type
132 
133 #if (VTK_USE_INT8 != 0)
134 template <class F>
135 inline void vtkResliceRound(F val, vtkTypeInt8 &rnd)
136 {
137  rnd = vtkResliceRound(val);
138 }
139 #endif
140 
141 #if (VTK_USE_UINT8 != 0)
142 template <class F>
143 inline void vtkResliceRound(F val, vtkTypeUInt8 &rnd)
144 {
145  rnd = vtkResliceRound(val);
146 }
147 #endif
148 
149 #if (VTK_USE_INT16 != 0)
150 template <class F>
151 inline void vtkResliceRound(F val, vtkTypeInt16 &rnd)
152 {
153  rnd = vtkResliceRound(val);
154 }
155 #endif
156 
157 #if (VTK_USE_UINT16 != 0)
158 template <class F>
159 inline void vtkResliceRound(F val, vtkTypeUInt16 &rnd)
160 {
161  rnd = vtkResliceRound(val);
162 }
163 #endif
164 
165 #if (VTK_USE_INT32 != 0)
166 template <class F>
167 inline void vtkResliceRound(F val, vtkTypeInt32 &rnd)
168 {
169  rnd = vtkResliceRound(val);
170 }
171 #endif
172 
173 #if (VTK_USE_UINT32 != 0)
174 template <class F>
175 inline void vtkResliceRound(F val, vtkTypeUInt32 &rnd)
176 {
177  rnd = vtkResliceRound(val);
178 }
179 #endif
180 
181 #if (VTK_USE_FLOAT32 != 0)
182 template <class F>
183 inline void vtkResliceRound(F val, vtkTypeFloat32 &rnd)
184 {
185  rnd = val;
186 }
187 #endif
188 
189 #if (VTK_USE_FLOAT64 != 0)
190 template <class F>
191 inline void vtkResliceRound(F val, vtkTypeFloat64 &rnd)
192 {
193  rnd = val;
194 }
195 #endif
196 
197 //----------------------------------------------------------------------------
198 // clamping functions for each type
199 
200 #if (VTK_USE_INT8 != 0)
201 template <class F>
202 inline void vtkResliceClamp(F val, vtkTypeInt8 &clamp)
203 {
204  if (val < -128.0)
205  {
206  val = -128.0;
207  }
208  if (val > 127.0)
209  {
210  val = 127.0;
211  }
212  vtkResliceRound(val, clamp);
213 }
214 #endif
215 
216 #if (VTK_USE_UINT8 != 0)
217 template <class F>
218 inline void vtkResliceClamp(F val, vtkTypeUInt8 &clamp)
219 {
220  if (val < 0)
221  {
222  val = 0;
223  }
224  if (val > 255.0)
225  {
226  val = 255.0;
227  }
228  vtkResliceRound(val, clamp);
229 }
230 #endif
231 
232 #if (VTK_USE_INT16 != 0)
233 template <class F>
234 inline void vtkResliceClamp(F val, vtkTypeInt16 &clamp)
235 {
236  if (val < -32768.0)
237  {
238  val = -32768.0;
239  }
240  if (val > 32767.0)
241  {
242  val = 32767.0;
243  }
244  vtkResliceRound(val, clamp);
245 }
246 #endif
247 
248 #if (VTK_USE_UINT16 != 0)
249 template <class F>
250 inline void vtkResliceClamp(F val, vtkTypeUInt16 &clamp)
251 {
252  if (val < 0)
253  {
254  val = 0;
255  }
256  if (val > 65535.0)
257  {
258  val = 65535.0;
259  }
260  vtkResliceRound(val, clamp);
261 }
262 #endif
263 
264 #if (VTK_USE_INT32 != 0)
265 template <class F>
266 inline void vtkResliceClamp(F val, vtkTypeInt32 &clamp)
267 {
268  if (val < -2147483648.0)
269  {
270  val = -2147483648.0;
271  }
272  if (val > 2147483647.0)
273  {
274  val = 2147483647.0;
275  }
276  vtkResliceRound(val, clamp);
277 }
278 #endif
279 
280 #if (VTK_USE_UINT32 != 0)
281 template <class F>
282 inline void vtkResliceClamp(F val, vtkTypeUInt32 &clamp)
283 {
284  if (val < 0)
285  {
286  val = 0;
287  }
288  if (val > 4294967295.0)
289  {
290  val = 4294967295.0;
291  }
292  vtkResliceRound(val, clamp);
293 }
294 #endif
295 
296 #if (VTK_USE_FLOAT32 != 0)
297 template <class F>
298 inline void vtkResliceClamp(F val, vtkTypeFloat32 &clamp)
299 {
300  clamp = val;
301 }
302 #endif
303 
304 #if (VTK_USE_FLOAT64 != 0)
305 template <class F>
306 inline void vtkResliceClamp(F val, vtkTypeFloat64 &clamp)
307 {
308  clamp = val;
309 }
310 #endif
311 
312 //----------------------------------------------------------------------------
313 // Perform a wrap to limit an index to [0,range).
314 // Ensures correct behaviour when the index is negative.
315 
316 inline int vtkInterpolateWrap(int num, int range)
317 {
318  if ((num %= range) < 0)
319  {
320  num += range; // required for some % implementations
321  }
322  return num;
323 }
324 
325 //----------------------------------------------------------------------------
326 // Perform a mirror to limit an index to [0,range).
327 
328 inline int vtkInterpolateMirror(int num, int range)
329 {
330  if (num < 0)
331  {
332  num = -num - 1;
333  }
334  int count = num / range;
335  num %= range;
336  if (count & 0x1)
337  {
338  num = range - num - 1;
339  }
340  return num;
341 }
342 
343 //----------------------------------------------------------------------------
344 // If the value is within one half voxel of the range [0,inExtX), then
345 // set it to "0" or "inExtX-1" as appropriate.
346 
347 inline int vtkInterpolateBorder(int &inIdX0, int &inIdX1, int inExtX, double fx)
348 {
349  if (inIdX0 >= 0 && inIdX1 < inExtX)
350  {
351  return 0;
352  }
353  if (inIdX0 == -1 && fx >= 0.5)
354  {
355  inIdX1 = inIdX0 = 0;
356  return 0;
357  }
358  if (inIdX0 == inExtX - 1 && fx < 0.5)
359  {
360  inIdX1 = inIdX0;
361  return 0;
362  }
363 
364  return 1;
365 }
366 
367 inline int vtkInterpolateBorderCheck(int inIdX0, int inIdX1, int inExtX, double fx)
368 {
369  if ((inIdX0 >= 0 && inIdX1 < inExtX) || (inIdX0 == -1 && fx >= 0.5) || (inIdX0 == inExtX - 1 && fx < 0.5))
370  {
371  return 0;
372  }
373 
374  return 1;
375 }
376 
377 //----------------------------------------------------------------------------
378 // Do nearest-neighbor interpolation of the input data 'inPtr' of extent
379 // 'inExt' at the 'point'. The result is placed at 'outPtr'.
380 // If the lookup data is beyond the extent 'inExt', set 'outPtr' to
381 // the background color 'background'.
382 // The number of scalar components in the data is 'numscalars'
383 template <class F, class T>
384 static int vtkNearestNeighborInterpolation(T *&outPtr,
385  const T *inPtr,
386  const int inExt[6],
387  const vtkIdType inInc[3],
388  int numscalars,
389  const F point[3],
390  int mode,
391  const T *background,
392  mitkVtkImageOverwrite *self)
393 {
394  int inIdX0 = vtkResliceRound(point[0]) - inExt[0];
395  int inIdY0 = vtkResliceRound(point[1]) - inExt[2];
396  int inIdZ0 = vtkResliceRound(point[2]) - inExt[4];
397 
398  int inExtX = inExt[1] - inExt[0] + 1;
399  int inExtY = inExt[3] - inExt[2] + 1;
400  int inExtZ = inExt[5] - inExt[4] + 1;
401 
402  if (inIdX0 < 0 || inIdX0 >= inExtX || inIdY0 < 0 || inIdY0 >= inExtY || inIdZ0 < 0 || inIdZ0 >= inExtZ)
403  {
404  if (mode == VTK_RESLICE_WRAP)
405  {
406  inIdX0 = vtkInterpolateWrap(inIdX0, inExtX);
407  inIdY0 = vtkInterpolateWrap(inIdY0, inExtY);
408  inIdZ0 = vtkInterpolateWrap(inIdZ0, inExtZ);
409  }
410  else if (mode == VTK_RESLICE_MIRROR)
411  {
412  inIdX0 = vtkInterpolateMirror(inIdX0, inExtX);
413  inIdY0 = vtkInterpolateMirror(inIdY0, inExtY);
414  inIdZ0 = vtkInterpolateMirror(inIdZ0, inExtZ);
415  }
416  else if (mode == VTK_RESLICE_BACKGROUND || mode == VTK_RESLICE_BORDER)
417  {
418  do
419  {
420  *outPtr++ = *background++;
421  } while (--numscalars);
422  return 0;
423  }
424  else
425  {
426  return 0;
427  }
428  }
429 
430  inPtr += inIdX0 * inInc[0] + inIdY0 * inInc[1] + inIdZ0 * inInc[2];
431 
432  do
433  {
434  if (!self->IsOverwriteMode())
435  {
436  // just copy from input to output
437  *outPtr++ = *inPtr++;
438  }
439  else
440  {
441  // copy from output to input in overwrite mode
442  *(const_cast<T *>(inPtr)) = *outPtr++;
443  inPtr++;
444  }
445  } while (--numscalars);
446 
447  return 1;
448 }
449 
450 //--------------------------------------------------------------------------
451 // get appropriate interpolation function according to scalar type
452 template <class F>
454  int (**interpolate)(void *&outPtr,
455  const void *inPtr,
456  const int inExt[6],
457  const vtkIdType inInc[3],
458  int numscalars,
459  const F point[3],
460  int mode,
461  const void *background,
462  mitkVtkImageOverwrite *self))
463 {
464  int dataType = self->GetOutput()->GetScalarType();
465 
466  switch (dataType)
467  {
468  vtkTemplateAliasMacro(*((int (**)(VTK_TT * &outPtr,
469  const VTK_TT *inPtr,
470  const int inExt[6],
471  const vtkIdType inInc[3],
472  int numscalars,
473  const F point[3],
474  int mode,
475  const VTK_TT *background,
477  default:
478  interpolate = nullptr;
479  }
480 }
481 
482 //----------------------------------------------------------------------------
483 // Some helper functions for 'RequestData'
484 //----------------------------------------------------------------------------
485 
486 //--------------------------------------------------------------------------
487 // pixel copy function, templated for different scalar types
488 template <class T>
489 struct vtkImageResliceSetPixels
490 {
491  static void Set(void *&outPtrV, const void *inPtrV, int numscalars, int n)
492  {
493  const T *inPtr = static_cast<const T *>(inPtrV);
494  T *outPtr = static_cast<T *>(outPtrV);
495  for (int i = 0; i < n; i++)
496  {
497  const T *tmpPtr = inPtr;
498  int m = numscalars;
499  do
500  {
501  *outPtr++ = *tmpPtr++;
502  } while (--m);
503  }
504  outPtrV = outPtr;
505  }
506 
507  // optimized for 1 scalar components
508  static void Set1(void *&outPtrV, const void *inPtrV, int vtkNotUsed(numscalars), int n)
509  {
510  const T *inPtr = static_cast<const T *>(inPtrV);
511  T *outPtr = static_cast<T *>(outPtrV);
512  T val = *inPtr;
513  for (int i = 0; i < n; i++)
514  {
515  *outPtr++ = val;
516  }
517  outPtrV = outPtr;
518  }
519 };
520 
521 // get a pixel copy function that is appropriate for the data type
523  void (**setpixels)(void *&out, const void *in, int numscalars, int n))
524 {
525  int dataType = self->GetOutput()->GetScalarType();
526  int numscalars = self->GetOutput()->GetNumberOfScalarComponents();
527 
528  switch (numscalars)
529  {
530  case 1:
531  switch (dataType)
532  {
533  vtkTemplateAliasMacro(*setpixels = &vtkImageResliceSetPixels<VTK_TT>::Set1);
534  default:
535  setpixels = nullptr;
536  }
537  default:
538  switch (dataType)
539  {
540  vtkTemplateAliasMacro(*setpixels = &vtkImageResliceSetPixels<VTK_TT>::Set);
541  default:
542  setpixels = nullptr;
543  }
544  }
545 }
546 
547 //----------------------------------------------------------------------------
548 // Convert background color from float to appropriate type
549 template <class T>
550 static void vtkAllocBackgroundPixelT(mitkVtkImageOverwrite *self, T **background_ptr, int numComponents)
551 {
552  *background_ptr = new T[numComponents];
553  T *background = *background_ptr;
554 
555  for (int i = 0; i < numComponents; i++)
556  {
557  if (i < 4)
558  {
559  vtkResliceClamp(self->GetBackgroundColor()[i], background[i]);
560  }
561  else
562  {
563  background[i] = 0;
564  }
565  }
566 }
567 
568 static void vtkAllocBackgroundPixel(mitkVtkImageOverwrite *self, void **rval, int numComponents)
569 {
570  switch (self->GetOutput()->GetScalarType())
571  {
572  vtkTemplateAliasMacro(vtkAllocBackgroundPixelT(self, (VTK_TT **)rval, numComponents));
573  }
574 }
575 
576 static void vtkFreeBackgroundPixel(mitkVtkImageOverwrite *self, void **rval)
577 {
578  switch (self->GetOutput()->GetScalarType())
579  {
580  vtkTemplateAliasMacro(delete[] * ((VTK_TT **)rval));
581  }
582 
583  *rval = nullptr;
584 }
585 
586 //----------------------------------------------------------------------------
587 // helper function for clipping of the output with a stencil
588 static int vtkResliceGetNextExtent(vtkImageStencilData *stencil,
589  int &r1,
590  int &r2,
591  int rmin,
592  int rmax,
593  int yIdx,
594  int zIdx,
595  void *&outPtr,
596  void *background,
597  int numscalars,
598  void (*setpixels)(void *&out, const void *in, int numscalars, int n),
599  int &iter)
600 {
601  // trivial case if stencil is not set
602  if (!stencil)
603  {
604  if (iter++ == 0)
605  {
606  r1 = rmin;
607  r2 = rmax;
608  return 1;
609  }
610  return 0;
611  }
612 
613  // for clearing, start at last r2 plus 1
614  int clear1 = r2 + 1;
615  if (iter == 0)
616  { // if no 'last time', start at rmin
617  clear1 = rmin;
618  }
619 
620  int rval = stencil->GetNextExtent(r1, r2, rmin, rmax, yIdx, zIdx, iter);
621  int clear2 = r1 - 1;
622  if (rval == 0)
623  {
624  clear2 = rmax;
625  }
626 
627  setpixels(outPtr, background, numscalars, clear2 - clear1 + 1);
628 
629  return rval;
630 }
631 
632 //----------------------------------------------------------------------------
633 // This function simply clears the entire output to the background color,
634 // for cases where the transformation places the output extent completely
635 // outside of the input extent.
637  mitkVtkImageOverwrite *self, vtkImageData *, void *, vtkImageData *outData, void *outPtr, int outExt[6], int id)
638 {
639  int numscalars;
640  int idY, idZ;
641  vtkIdType outIncX, outIncY, outIncZ;
642  int scalarSize;
643  unsigned long count = 0;
644  unsigned long target;
645  void *background;
646  void (*setpixels)(void *&out, const void *in, int numscalars, int n);
647 
648  // for the progress meter
649  target = static_cast<unsigned long>((outExt[5] - outExt[4] + 1) * (outExt[3] - outExt[2] + 1) / 50.0);
650  target++;
651 
652  // Get Increments to march through data
653  outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ);
654  scalarSize = outData->GetScalarSize();
655  numscalars = outData->GetNumberOfScalarComponents();
656 
657  // allocate a voxel to copy into the background (out-of-bounds) regions
658  vtkAllocBackgroundPixel(self, &background, numscalars);
659  // get the appropriate function for pixel copying
660  vtkGetSetPixelsFunc(self, &setpixels);
661 
662  // Loop through output voxels
663  for (idZ = outExt[4]; idZ <= outExt[5]; idZ++)
664  {
665  for (idY = outExt[2]; idY <= outExt[3]; idY++)
666  {
667  if (id == 0)
668  { // update the progress if this is the main thread
669  if (!(count % target))
670  {
671  self->UpdateProgress(count / (50.0 * target));
672  }
673  count++;
674  }
675  // clear the pixels to background color and go to next row
676  setpixels(outPtr, background, numscalars, outExt[1] - outExt[0] + 1);
677  outPtr = static_cast<void *>(static_cast<char *>(outPtr) + outIncY * scalarSize);
678  }
679  outPtr = static_cast<void *>(static_cast<char *>(outPtr) + outIncZ * scalarSize);
680  }
681 
682  vtkFreeBackgroundPixel(self, &background);
683 }
684 
685 //----------------------------------------------------------------------------
686 // This function executes the filter for any type of data. It is much simpler
687 // in structure than vtkImageResliceOptimizedExecute.
689  vtkImageData *inData,
690  void *inPtr,
691  vtkImageData *outData,
692  void *outPtr,
693  int outExt[6],
694  int id)
695 {
696  int numscalars;
697  int idX, idY, idZ;
698  int idXmin, idXmax, iter;
699  vtkIdType outIncX, outIncY, outIncZ;
700  int scalarSize;
701  int inExt[6];
702  vtkIdType inInc[3];
703  unsigned long count = 0;
704  unsigned long target;
705  double point[4];
706  double f;
707  double *inSpacing, *inOrigin, *outSpacing, *outOrigin, inInvSpacing[3];
708  void *background;
709  int (*interpolate)(void *&outPtr,
710  const void *inPtr,
711  const int inExt[6],
712  const vtkIdType inInc[3],
713  int numscalars,
714  const double point[3],
715  int mode,
716  const void *background,
717  mitkVtkImageOverwrite *self) = nullptr;
718  void (*setpixels)(void *&out, const void *in, int numscalars, int n) = nullptr;
719 
720  // the 'mode' species what to do with the 'pad' (out-of-bounds) area
721  int mode = VTK_RESLICE_BACKGROUND;
722  if (self->GetMirror())
723  {
724  mode = VTK_RESLICE_MIRROR;
725  }
726  else if (self->GetWrap())
727  {
728  mode = VTK_RESLICE_WRAP;
729  }
730  else if (self->GetBorder())
731  {
732  mode = VTK_RESLICE_BORDER;
733  }
734 
735  // the transformation to apply to the data
736  vtkAbstractTransform *transform = self->GetResliceTransform();
737  vtkMatrix4x4 *matrix = self->GetResliceAxes();
738 
739  // for conversion to data coordinates
740  inOrigin = inData->GetOrigin();
741  inSpacing = inData->GetSpacing();
742  outOrigin = outData->GetOrigin();
743  outSpacing = outData->GetSpacing();
744 
745  // save effor later: invert inSpacing
746  inInvSpacing[0] = 1.0 / inSpacing[0];
747  inInvSpacing[1] = 1.0 / inSpacing[1];
748  inInvSpacing[2] = 1.0 / inSpacing[2];
749 
750  // find maximum input range
751  inData->GetExtent(inExt);
752 
753  // for the progress meter
754  target = static_cast<unsigned long>((outExt[5] - outExt[4] + 1) * (outExt[3] - outExt[2] + 1) / 50.0);
755  target++;
756 
757  // Get Increments to march through data
758  inData->GetIncrements(inInc);
759  outData->GetContinuousIncrements(outExt, outIncX, outIncY, outIncZ);
760  scalarSize = outData->GetScalarSize();
761  numscalars = inData->GetNumberOfScalarComponents();
762 
763  // allocate a voxel to copy into the background (out-of-bounds) regions
764  vtkAllocBackgroundPixel(self, &background, numscalars);
765 
766  // get the appropriate functions for interpolation and pixel copying
767  vtkGetResliceInterpFunc(self, &interpolate);
768  vtkGetSetPixelsFunc(self, &setpixels);
769 
770  // get the stencil
771  vtkImageStencilData *stencil = self->GetStencil();
772 
773  // Loop through output voxels
774  for (idZ = outExt[4]; idZ <= outExt[5]; idZ++)
775  {
776  for (idY = outExt[2]; idY <= outExt[3]; idY++)
777  {
778  if (id == 0)
779  { // update the progress if this is the main thread
780  if (!(count % target))
781  {
782  self->UpdateProgress(count / (50.0 * target));
783  }
784  count++;
785  }
786 
787  iter = 0; // if there is a stencil, it is applied here
789  stencil, idXmin, idXmax, outExt[0], outExt[1], idY, idZ, outPtr, background, numscalars, setpixels, iter))
790  {
791  for (idX = idXmin; idX <= idXmax; idX++)
792  {
793  // convert to data coordinates
794  point[0] = idX * outSpacing[0] + outOrigin[0];
795  point[1] = idY * outSpacing[1] + outOrigin[1];
796  point[2] = idZ * outSpacing[2] + outOrigin[2];
797 
798  // apply ResliceAxes matrix
799  if (matrix)
800  {
801  point[3] = 1.0;
802  matrix->MultiplyPoint(point, point);
803  f = 1.0 / point[3];
804  point[0] *= f;
805  point[1] *= f;
806  point[2] *= f;
807  }
808 
809  // apply ResliceTransform
810  if (transform)
811  {
812  transform->InternalTransformPoint(point, point);
813  }
814 
815  // convert back to voxel indices
816  point[0] = (point[0] - inOrigin[0]) * inInvSpacing[0];
817  point[1] = (point[1] - inOrigin[1]) * inInvSpacing[1];
818  point[2] = (point[2] - inOrigin[2]) * inInvSpacing[2];
819 
820  // interpolate output voxel from input data set
821  interpolate(outPtr, inPtr, inExt, inInc, numscalars, point, mode, background, self);
822  }
823  }
824  outPtr = static_cast<void *>(static_cast<char *>(outPtr) + outIncY * scalarSize);
825  }
826  outPtr = static_cast<void *>(static_cast<char *>(outPtr) + outIncZ * scalarSize);
827  }
828 
829  vtkFreeBackgroundPixel(self, &background);
830 }
831 
833 {
834  m_Overwrite_Mode = b;
835 }
836 
837 void mitkVtkImageOverwrite::SetInputSlice(vtkImageData *slice)
838 {
839  // set the output as input
840  this->SetOutput(slice);
841 }
842 
843 //----------------------------------------------------------------------------
844 // This method is passed a input and output region, and executes the filter
845 // algorithm to fill the output from the input or vice versa.
846 void mitkVtkImageOverwrite::ThreadedRequestData(vtkInformation *vtkNotUsed(request),
847  vtkInformationVector **vtkNotUsed(inputVector),
848  vtkInformationVector *vtkNotUsed(outputVector),
849  vtkImageData ***inData,
850  vtkImageData **outData,
851  int outExt[6],
852  int id)
853 {
854  vtkDebugMacro(<< "Execute: inData = " << inData[0][0] << ", outData = " << outData[0]);
855  // this filter expects that input is the same type as output.
856  if (inData[0][0]->GetScalarType() != outData[0]->GetScalarType())
857  {
858  vtkErrorMacro(<< "Execute: input ScalarType, " << inData[0][0]->GetScalarType() << ", must match out ScalarType "
859  << outData[0]->GetScalarType());
860  return;
861  }
862 
863  int inExt[6];
864  inData[0][0]->GetExtent(inExt);
865  // check for empty input extent
866  if (inExt[1] < inExt[0] || inExt[3] < inExt[2] || inExt[5] < inExt[4])
867  {
868  return;
869  }
870 
871  // Get the output pointer
872  void *outPtr = outData[0]->GetScalarPointerForExtent(outExt);
873 
874  if (this->HitInputExtent == 0)
875  {
876  vtkImageResliceClearExecute(this, inData[0][0], nullptr, outData[0], outPtr, outExt, id);
877  return;
878  }
879 
880  // Now that we know that we need the input, get the input pointer
881  void *inPtr = inData[0][0]->GetScalarPointerForExtent(inExt);
882 
883  vtkImageResliceExecute(this, inData[0][0], inPtr, outData[0], outPtr, outExt, id);
884 }
#define VTK_RESLICE_BACKGROUND
int vtkResliceFloor(double x, F &f)
static void vtkImageResliceClearExecute(mitkVtkImageOverwrite *self, vtkImageData *, void *, vtkImageData *outData, void *outPtr, int outExt[6], int id)
int vtkInterpolateWrap(int num, int range)
vtkStandardNewMacro(mitkVtkImageOverwrite)
static void vtkGetSetPixelsFunc(mitkVtkImageOverwrite *self, void(**setpixels)(void *&out, const void *in, int numscalars, int n))
#define VTK_RESLICE_BORDER
int vtkInterpolateBorder(int &inIdX0, int &inIdX1, int inExtX, double fx)
static int vtkNearestNeighborInterpolation(T *&outPtr, const T *inPtr, const int inExt[6], const vtkIdType inInc[3], int numscalars, const F point[3], int mode, const T *background, mitkVtkImageOverwrite *self)
static int vtkResliceGetNextExtent(vtkImageStencilData *stencil, int &r1, int &r2, int rmin, int rmax, int yIdx, int zIdx, void *&outPtr, void *background, int numscalars, void(*setpixels)(void *&out, const void *in, int numscalars, int n), int &iter)
static void vtkAllocBackgroundPixelT(mitkVtkImageOverwrite *self, T **background_ptr, int numComponents)
int vtkInterpolateMirror(int num, int range)
A vtk Filter based on vtkImageReslice with the aditional feature to write a slice into the given inpu...
static void vtkGetResliceInterpFunc(mitkVtkImageOverwrite *self, int(**interpolate)(void *&outPtr, const void *inPtr, const int inExt[6], const vtkIdType inInc[3], int numscalars, const F point[3], int mode, const void *background, mitkVtkImageOverwrite *self))
static void vtkImageResliceExecute(mitkVtkImageOverwrite *self, vtkImageData *inData, void *inPtr, vtkImageData *outData, void *outPtr, int outExt[6], int id)
static void vtkFreeBackgroundPixel(mitkVtkImageOverwrite *self, void **rval)
int vtkInterpolateBorderCheck(int inIdX0, int inIdX1, int inExtX, double fx)
static bool in(Reader::Char c, Reader::Char c1, Reader::Char c2, Reader::Char c3, Reader::Char c4)
Definition: jsoncpp.cpp:244
static void vtkAllocBackgroundPixel(mitkVtkImageOverwrite *self, void **rval, int numComponents)
void SetOverwriteMode(bool b)
Set the mode either to reslice (false) or to overwrite (true). Default: false.
virtual void ThreadedRequestData(vtkInformation *vtkNotUsed(request), vtkInformationVector **vtkNotUsed(inputVector), vtkInformationVector *vtkNotUsed(outputVector), vtkImageData ***inData, vtkImageData **outData, int outExt[6], int id) override
#define VTK_RESLICE_WRAP
int vtkResliceRound(double x)
* background
Definition: ad.h:1
void SetInputSlice(vtkImageData *slice)
Set the slice for overwrite mode. Note: It is recommend not to use this in reslice mode because other...
#define VTK_RESLICE_MIRROR