MeVisLab Toolbox Reference
mlTSubImage.h
Go to the documentation of this file.
1 /*************************************************************************************
2 **
3 ** Copyright 2007, MeVis Medical Solutions AG
4 **
5 ** The user may use this file in accordance with the license agreement provided with
6 ** the Software or, alternatively, in accordance with the terms contained in a
7 ** written agreement between the user and MeVis Medical Solutions AG.
8 **
9 ** For further information use the contact form at https://www.mevislab.de/contact
10 **
11 **************************************************************************************/
12 
13 #ifndef ML_TSUB_IMAGE_H
14 #define ML_TSUB_IMAGE_H
15 
19 
20 // ML-includes
21 #include "mlInitSystemML.h"
22 #include "mlSubImage.h"
23 #include "mlTypeTraits.h"
24 
25 #include "mlTemplateSupport.h"
26 
27 #ifdef _MSC_VER
28 #pragma warning(push)
29 // warning C4244: 'Argument': Konvertierung von 'typ1' in 'typ2', m�glicher Datenverlust
30 #pragma warning(disable: 4244)
31 #endif
32 
33 ML_START_NAMESPACE
34 
35 
36 
37 
39 template <typename DATATYPE> class TSubImageCursor;
41 template <typename DATATYPE> class ConstTSubImageCursor;
42 
44 #define _ML_TSUBIMG_SUBDOT6(pos, offset, stride) \
45  (((pos).x - (offset).x) * (stride).x + \
46  ((pos).y - (offset).y) * (stride).y + \
47  ((pos).z - (offset).z) * (stride).z + \
48  ((pos).c - (offset).c) * (stride).c + \
49  ((pos).t - (offset).t) * (stride).t + \
50  ((pos).u - (offset).u) * (stride).u)
51 
53 #define _ML_TSUBIMG_SUBDOT3(x, y, z, offset, stride) \
54  (((x) - (offset).x) * (stride).x + \
55  ((y) - (offset).y) * (stride).y + \
56  ((z) - (offset).z) * (stride).z)
57 
59 #define _ML_TSUBIMG_SUBDOT2(x, y, offset, stride) \
60  (((x) - (offset).x) * (stride).x + \
61  ((y) - (offset).y) * (stride).y)
62 
63 
64 //-------------------------------------------------------------------------
107 //-------------------------------------------------------------------------
108 template <typename DATATYPE>
109 class TSubImage : public SubImage
110 {
111 
112 public:
113 
115  typedef DATATYPE ComponentType;
116 
121 
122  //---------------------------------------------------------------------------
125  //---------------------------------------------------------------------------
137  TSubImage(const SubImageBox& box, MLDataType dataType, void* data):SubImage(box, dataType, data)
138  {
139  // Check whether template type and real data type match if there is valid data.
140  if (data && !TypeTraits<DATATYPE>::matches(dataType) )
141  {
142  ML_PRINT_FATAL_ERROR("TSubImage::TSubImage()", ML_BAD_DATA_TYPE,
143  "Mismatch of data type between argument and template typename.");
144  }
145  }
146 
153  {
154  // Set correct data type enum from template data type.
155  setDataType(TypeTraits<DATATYPE>::dataType);
157  ML_PRINT_FATAL_ERROR("TSubImage::TSubImage()", ML_BAD_DATA_TYPE,
158  "Data type has no registered TypeTraits.");
159  }
160  }
161 
162 
169  TSubImage(const SubImage &subImage)
170  {
171  // Sets box the data is correlated with.
172  setBox(subImage.getBox());
173 
174  // Sets correct data type enum.
175  setDataType(subImage.getDataType());
176 
177  // Stores data pointer (but \e not the memory block handle).
178  setData(subImage.getData());
179 
180  // Sets the source image extent.
181  setSourceImageExtent(subImage.getSourceImageExtent());
182 
183  // Checks whether template type and real data type match if there is valid data.
184  // This check only works if TypeTraits has been specified for the argument type.
185  if (subImage.getData() && !TypeTraits<DATATYPE>::matches(subImage.getDataType()) )
186  {
187  ML_PRINT_FATAL_ERROR("TSubImage::TSubImage()", ML_BAD_DATA_TYPE,
188  "Mismatch of data type between argument and template typename.");
189  }
190  }
191 
194  inline TSubImage(const TSubImage<DATATYPE>& typedSubImage) :
195  SubImage (typedSubImage)
196  {
197  }
198 
200  inline ~TSubImage() override = default;
201 
204  inline TSubImage &operator=(const TSubImage<DATATYPE>& typedSubImage)
205  {
206  SubImage::operator=(typedSubImage);
207  return *this;
208  }
210 
211  //---------------------------------------------------------------------------
214  //---------------------------------------------------------------------------
215 
217  inline const DATATYPE* getData() const { return static_cast<DATATYPE*>(_data); }
218  inline DATATYPE* getData() { return static_cast<DATATYPE*>(_data); }
219 
221 
222  //---------------------------------------------------------------------------
225  //---------------------------------------------------------------------------
229  // 64-bit arithmetic is not needed here, because the pointer offset goes from the valid
230  // address space to another position inside the valid address space. We do not
231  // fall outside 32-bit ranges.
233  inline const DATATYPE* getSubImagePointer(const ImageVector& position) const { return static_cast<DATATYPE*>(_data) + ImageVector::dot(position,_stride); }
234  inline DATATYPE* getSubImagePointer(const ImageVector& position) { return static_cast<DATATYPE*>(_data) + ImageVector::dot(position,_stride); }
236 
241  // 64-bit arithmetic is not needed here, because the pointer offset goes from the valid
242  // address space to another position inside the valid address space. We do not
243  // fall outside 32-bit ranges.
245  inline const DATATYPE* getSubImagePointer(MLint x, MLint y, MLint z) const { return static_cast<DATATYPE*>(_data) + (x*_stride.x + y*_stride.y + _stride.z*z); }
246  inline DATATYPE* getSubImagePointer(MLint x, MLint y, MLint z) { return static_cast<DATATYPE*>(_data) + (x*_stride.x + y*_stride.y + _stride.z*z); }
248 
253  inline const DATATYPE* getImagePointer(const ImageVector& position) const { return static_cast<DATATYPE*>(_data) + _ML_TSUBIMG_SUBDOT6(position, _box.v1, _stride); }
254  inline DATATYPE* getImagePointer(const ImageVector& position) { return static_cast<DATATYPE*>(_data) + _ML_TSUBIMG_SUBDOT6(position, _box.v1, _stride); }
256 
261  inline const DATATYPE* getImagePointer(MLint x, MLint y, MLint z) const { return static_cast<DATATYPE*>(_data) + _ML_TSUBIMG_SUBDOT3(x,y,z, _box.v1, _stride); }
262  inline DATATYPE* getImagePointer(MLint x, MLint y, MLint z) { return static_cast<DATATYPE*>(_data) + _ML_TSUBIMG_SUBDOT3(x,y,z, _box.v1, _stride); }
265 
266 
267  //-------------------------------------------------------------------------------------
270  //-------------------------------------------------------------------------------------
274  inline ImageVector convertPointerToSubImagePosition(DATATYPE* pointer) const
275  { return getStride().getVectorPosition(pointer - static_cast<DATATYPE*>(_data)); }
276 
282  inline void convertPointerToSubImagePosition(DATATYPE* pointer, MLint* x, MLint* y, MLint* z) const
283  {
284  const MLint offset = pointer - static_cast<DATATYPE*>(_data);
285  const ImageVector stride=getStride();
286  const ImageVector imgExt=getImageExtent();
287 
288  if (x){
289  ML_CHECK_THROW(stride.x);
290  ML_CHECK_THROW(imgExt.x);
291  *x = (offset/stride.x) % imgExt.x;
292  }
293 
294  if (y){
295  ML_CHECK_THROW(imgExt.y);
296  ML_CHECK_THROW(stride.y);
297  *y = (offset/stride.y) % imgExt.y;
298  }
299 
300  if (z){
301  ML_CHECK_THROW(imgExt.z);
302  ML_CHECK_THROW(stride.z);
303  *z = (offset/stride.z) % imgExt.z;
304  }
305  }
306 
307 
311  inline ImageVector convertPointerToImagePosition(DATATYPE* pointer) const
312  { return convertPointerToSubImagePosition(pointer) + _box.v1; }
313 
314 
320  inline void convertPointerToImagePosition(DATATYPE* pointer, MLint* x, MLint* y, MLint* z) const
321  {
322  convertPointerToSubImagePosition(pointer, x, y, z);
323  if (x){ *x += _box.v1.x; }
324  if (y){ *y += _box.v1.y; }
325  if (z){ *z += _box.v1.z; }
326  }
328 
329 
330 
331  //---------------------------------------------------------------------------
334  //---------------------------------------------------------------------------
335 
340  inline const DATATYPE& operator[](const ImageVector& position) const { return getImagePointer(position)[0]; }
341 
346  inline DATATYPE& operator[](const ImageVector& position) { return getImagePointer(position)[0]; }
347 
351  inline void setSubImageValue(const ImageVector& position, DATATYPE value) { static_cast<DATATYPE*>(_data)[ ImageVector::dot(position,_stride) ]=value; }
352 
356  inline DATATYPE getSubImageValue(const ImageVector& position) const { return static_cast<DATATYPE*>(_data)[ ImageVector::dot(position,_stride) ]; }
357 
361  inline void setSubImageValue(MLint x, MLint y, DATATYPE value) { static_cast<DATATYPE*>(_data)[ x*_stride.x + y*_stride.y ]=value; }
365  inline DATATYPE getSubImageValue(MLint x, MLint y) const { return static_cast<DATATYPE*>(_data)[ x*_stride.x + y*_stride.y ]; }
366 
370  inline void setSubImageValue(MLint x, MLint y, MLint z, DATATYPE value){ static_cast<DATATYPE*>(_data)[ x*_stride.x + y*_stride.y+_stride.z*z ]=value; }
374  inline DATATYPE getSubImageValue(MLint x, MLint y, MLint z) const { return static_cast<DATATYPE*>(_data)[ x*_stride.x + y*_stride.y+_stride.z*z ]; }
375 
379  inline void setImageValue(const ImageVector& position, DATATYPE value) { getImagePointer(position)[0] = value; }
383  inline DATATYPE getImageValue(const ImageVector& position) const { return getImagePointer(position)[0]; }
384 
388  inline void setImageValue(MLint x, MLint y, DATATYPE value) { static_cast<DATATYPE*>(_data)[_ML_TSUBIMG_SUBDOT2(x,y,_box.v1, _stride)]=value; }
392  inline DATATYPE getImageValue(MLint x, MLint y) const { return static_cast<DATATYPE*>(_data)[_ML_TSUBIMG_SUBDOT2(x,y,_box.v1, _stride)]; }
393 
397  inline void setImageValue(MLint x, MLint y, MLint z, DATATYPE value){ getImagePointer(x,y,z)[0] = value; }
401  inline DATATYPE getImageValue(MLint x, MLint y, MLint z) const { return getImagePointer(x,y,z)[0]; }
402 
404 
405 
406  //---------------------------------------------------------------------------
409  //---------------------------------------------------------------------------
420  MLint calculateMinMax(DATATYPE& minValue, DATATYPE& maxValue, const SubImageBox * const validBox=nullptr) const
421  {
422  // If passed box pointer is valid, then compute intersection with
423  // this subimage box, otherwise use non intersected subimage box of this.
424  const SubImageBox& thisBox = getBox();
425  const SubImageBox box = validBox ? SubImageBox::intersect(thisBox, *validBox) : thisBox;
426 
427  // Return number of voxels in subimage. Return 0/0 if subimage is empty.
428  const MLint numVoxels = box.getNumVoxels();
429  if (numVoxels==0){ minValue=0; maxValue=0; return 0; }
430 
431  // Set min/max to first voxel value.
432  minValue = maxValue = getImageValue(box.v1);
433 
434  // Simply scan all voxels. If box is subimage box, it is faster.
435  if (box == thisBox){
436  // Not empty. Get pointer to voxel directly after last voxel.
437 
438  ML_CHECK_THROW(_data);
439  const DATATYPE* dataEnd = static_cast<DATATYPE*>(_data) + numVoxels;
440 
441  // Scan all voxels starting with the second one.
442  for (DATATYPE* i=static_cast<DATATYPE*>(_data)+1; i<dataEnd; ++i)
443  {
444  if (*i < minValue){ minValue = *i; }
445  if (*i > maxValue){ maxValue = *i; }
446  }
447  }
448  else{
449  // Loop over all rows of the valid subimage region.
450  ImageVector p;
451  for (MLint u=box.v1.u; u <= box.v2.u; ++u){
452  for (MLint t=box.v1.t; t <= box.v2.t; ++t){
453  for (MLint c=box.v1.c; c <= box.v2.c; ++c){
454  for (MLint z=box.v1.z; z <= box.v2.z; ++z){
455  for (MLint y=box.v1.y; y <= box.v2.y; ++y){
456  // For inner loop, move pointer.
457  p.set(box.v1.x, y, z, c, t, u);
458  const DATATYPE *dPtr = getImagePointer(p);
459  const MLint pEnd = box.v2.x;
460  for (MLint x=box.v1.x; x <= pEnd; ++x, ++dPtr){
461  if (*dPtr < minValue){ minValue = *dPtr; }
462  if (*dPtr > maxValue){ maxValue = *dPtr; }
463  }
464  }
465  }
466  }
467  }
468  }
469  }
470 
471  // Return how many voxel have been scanned.
472  return numVoxels;
473  };
475 
476  //---------------------------------------------------------------------------
479  //---------------------------------------------------------------------------
480 
482 #define _ML_CHECK_SUBIMAGE_DATA_POINTERS(FROM_PTR, TO_PTR) \
483  /* Check for valid data pointers to avoid memory access errors. */ \
484  { \
485  if (!FROM_PTR || !TO_PTR){ \
486  ML_PRINT_ERROR("TSubImage::copySubImageTyped( )", \
487  ML_BAD_POINTER_OR_0, \
488  "Valid data pointers in source and target subimage required for" \
489  "subimage copying, thus call is ignored."); \
490  return; \
491  } \
492  }
493 
497  template <typename FROM_DATATYPE>
499  {
500  // Copy in local variables to reduce calculations in getBox().
501  const SubImageBox& box =getBox();
502  const SubImageBox& tBox=typedFromImage.getBox();
503 
504  if (box.isEmpty() || tBox.isEmpty()){ return; }
505 
506  // Calculate overlap of both subimages and copy only if overlap is not empty.
507  const SubImageBox intersection = SubImageBox::intersect(typedFromImage.getBox(),getBox());
508  if (!intersection.isEmpty()){
509 
510  // Check data pointers and print errors if necessary.
511  _ML_CHECK_SUBIMAGE_DATA_POINTERS(typedFromImage.getData(), getData());
512 
513  ImageVector p;
514  const FROM_DATATYPE* fromPt = nullptr;
515  DATATYPE* toPt = nullptr;
516 
517  const ImageVector toExtent = getExtent();
518  const ImageVector toStrides = ImageVector(toExtent.c, toExtent.x, toExtent.y, toExtent.z, toExtent.t, toExtent.u).getStrides();
519  const ImageVector offsetReordered(_box.v1.c, _box.v1.x, _box.v1.y, _box.v1.z, _box.v1.t, _box.v1.u);
520 
521  const MLdouble scaleDbl = static_cast<MLdouble>(scaleShiftData.getScale());
522  const MLdouble shiftDbl = static_cast<MLdouble>(scaleShiftData.getShift());
523 
524  // Check for identical scaling.
525  const bool identicalScaling = MLValuesAreEqual(scaleDbl, static_cast<MLdouble>(1), static_cast<MLdouble>(1)) &&
526  MLValuesAreEqual(shiftDbl, static_cast<MLdouble>(0), static_cast<MLdouble>(1));
527 
528  // Traverse all voxels.
529  if (identicalScaling) {
530  for (p.u=intersection.v1.u; p.u<=intersection.v2.u; ++p.u) {
531  for (p.t=intersection.v1.t; p.t<=intersection.v2.t; ++p.t) {
532  for (p.c=intersection.v1.c; p.c<=intersection.v2.c; ++p.c) {
533  for (p.z=intersection.v1.z; p.z<=intersection.v2.z; ++p.z) {
534  for (p.y=intersection.v1.y; p.y<=intersection.v2.y; ++p.y) {
535 
536  const ImageVector pos(intersection.v1.x,p.y,p.z,p.c,p.t,p.u);
537  const ImageVector posReordered(p.c, intersection.v1.x,p.y,p.z,p.t,p.u);
538  fromPt= typedFromImage.getImagePointer(pos);
539  toPt = static_cast<DATATYPE*>(_data) + _ML_TSUBIMG_SUBDOT6(posReordered, offsetReordered, toStrides);
540 
541  for (p.x = intersection.v1.x; p.x <= intersection.v2.x; ++p.x, ++fromPt) {
542  *toPt = static_cast<DATATYPE>(*fromPt);
543  toPt += toStrides.y;
544  }
545  }
546  }
547  }
548  }
549  }
550  } else {
551  for (p.u=intersection.v1.u; p.u<=intersection.v2.u; ++p.u) {
552  for (p.t=intersection.v1.t; p.t<=intersection.v2.t; ++p.t) {
553  for (p.c=intersection.v1.c; p.c<=intersection.v2.c; ++p.c) {
554  for (p.z=intersection.v1.z; p.z<=intersection.v2.z; ++p.z) {
555  for (p.y=intersection.v1.y; p.y<=intersection.v2.y; ++p.y) {
556 
557  const ImageVector pos(intersection.v1.x,p.y,p.z,p.c,p.t,p.u);
558  const ImageVector posReordered(p.c, intersection.v1.x,p.y,p.z,p.t,p.u);
559  fromPt= typedFromImage.getImagePointer(pos);
560  toPt = static_cast<DATATYPE*>(_data) + _ML_TSUBIMG_SUBDOT6(posReordered, offsetReordered, toStrides);
561 
562  for (p.x = intersection.v1.x; p.x <= intersection.v2.x; ++p.x, ++fromPt) {
563  *toPt = static_cast<DATATYPE>(static_cast<MLdouble>(*fromPt)*scaleDbl + shiftDbl);
564  toPt += toStrides.y;
565  }
566  }
567  }
568  }
569  }
570  }
571  }
572  } // if (!intersection.isEmpty())
573  }
574 
586  //
587  //Note: The following function definition must be implemented in the class definition
588  // See BUG: LNK2001 on Member Function When Use Nested Class Template, Article ID: Q128789
589  template <typename FROM_DATATYPE>
590  void copySubImageTyped(const TSubImage<FROM_DATATYPE> &typedFromImg, const ScaleShiftData& scaleShiftData)
591  {
592  // Any box empty? Then no copy is necessary.
593  if (getBox().isEmpty() || typedFromImg.getBox().isEmpty()){
594  return;
595  }
596 
597  if (scaleShiftData.getReorderMode() == ScaleShiftData::ReorderColorPlanesToInterleaved) {
598  copySubImageReorderColorPlanesToInterleaved(typedFromImg, scaleShiftData);
599  return;
600  }
601 
602  // Get double and long double versions of scale and shift values.
603  const MLdouble scaleDbl = scaleShiftData.getScale();
604  const MLdouble shiftDbl = scaleShiftData.getShift();
605 
606  // Check for identical scaling and use default copying then.
607  if (MLValuesAreEqual(scaleDbl, 1.0, 1.0) && MLValuesAreEqual(shiftDbl, 0.0, 1.0)){
608  copySubImage(typedFromImg);
609  return;
610  }
611 
612  // Get data type properties. If we calculate with normal datatypes then we calculate in double values;
613  // on long double built-in types we use long double, and if we use extended types we remain in extended types.
614  const MLint isDTScalarType = MLIsScalarTypePtr(static_cast<DATATYPE*>(nullptr));
615  const MLint isFDTScalarType = MLIsScalarTypePtr(static_cast<FROM_DATATYPE*>(nullptr));
616 
617  if (getDataType()==typedFromImg.getDataType()){
618  if (getBox()==typedFromImg.getBox()){
619  // Images have same data type and same position/extent:
620  //-----------------------------------------------------
621  const FROM_DATATYPE *fromPt = typedFromImg.getData();
622  DATATYPE *toPt = getData();
623 
624  // Check data pointers and print errors if necessary.
625  _ML_CHECK_SUBIMAGE_DATA_POINTERS(fromPt, toPt);
626 
627  // Get number and the size in bytes of all voxels of this subimage.
628  const MLint size = getNumVoxels();
629  const MLint bytesize = size * MLSizeOf(getDataType());
630 
631  // Copy the memory to the target buffer, it must fit since types are identical.
632  memcpy( toPt, fromPt, bytesize );
633 
634  // When we work with extended types we must avoid to change to double during calculations since
635  // that causes information loss. In normal case we remain in double.
636  if (!isDTScalarType){
637  // NOTE/TODO:
638  // Currently extended types must support adding and multiplying with doubles
639  // for this to work.
640  for (DATATYPE* toPtEnd=toPt+size; toPt<toPtEnd; ++toPt){
641  *toPt=static_cast<DATATYPE>(static_cast<DATATYPE>(*toPt)*scaleDbl + shiftDbl);
642  }
643  }
644  else{
645  for (DATATYPE* toPtEnd=toPt+size; toPt<toPtEnd; ++toPt){
646  *toPt=static_cast<DATATYPE>( static_cast<MLdouble>(*toPt)*scaleDbl + shiftDbl);
647  }
648  }
649  }
650  else{
651  // Images have same data type:
652  //----------------------------
653  // Calculate intersection of both subimages. Copy only if intersection is not empty.
654  const SubImageBox intersection = SubImageBox::intersect(typedFromImg.getBox(),getBox());
655  if (!intersection.isEmpty()){
656 
657  // Check data pointers and print errors if necessary.
658  _ML_CHECK_SUBIMAGE_DATA_POINTERS(typedFromImg.getData(), getData());
659 
660  ImageVector p;
661  const FROM_DATATYPE *fromPt = nullptr;
662  DATATYPE *toPt = nullptr,
663  *toPt_ = nullptr,
664  *toPtEnd = nullptr;
665  const ImageVector fromStr = typedFromImg.getStride();
666  const ImageVector toStr = getStride();
667  const MLint dist = intersection.v2.x - intersection.v1.x;
668  const MLint size_x = dist+1;
669  const MLint bytesize_x = size_x * MLSizeOf(getDataType());
670 
671  // Traverse all 6 dimensions.
672  for (p.u=intersection.v1.u; p.u<=intersection.v2.u; ++p.u){
673  for (p.t=intersection.v1.t; p.t<=intersection.v2.t; ++p.t){
674  for (p.c=intersection.v1.c; p.c<=intersection.v2.c; ++p.c){
675  for (p.z=intersection.v1.z; p.z<=intersection.v2.z; ++p.z){
676 
677  // Get start position to each slice of data.
678  const ImageVector pos(intersection.v1.x, intersection.v1.y, p.z, p.c, p.t, p.u);
679  fromPt = typedFromImg.getImagePointer(pos);
680  toPt = getImagePointer(pos);
681  ML_CHECK_THROW(fromPt);
682  ML_CHECK_THROW(toPt);
683 
684  for (p.y=intersection.v1.y; p.y<=intersection.v2.y; ++p.y,fromPt+=fromStr.y,toPt+=toStr.y){
685 
686  // Copy buffer to target buffer. Below we work only on one buffer for rescaling.
687  memcpy(toPt, fromPt, bytesize_x);
688  toPt_ = toPt;
689 
690  if (!isDTScalarType){
691  // See description in upper case "if (getDataType()==typedFromImg.getDataType())".
692  for (toPtEnd = toPt_+size_x;
693  toPt_<toPtEnd;
694  ++toPt_){
695  *toPt_=static_cast<DATATYPE>(static_cast<DATATYPE>(*toPt_)*scaleDbl + shiftDbl);
696  }
697  }
698  else{
699  for (toPtEnd = toPt_+size_x;
700  toPt_<toPtEnd;
701  ++toPt_){
702  *toPt_=static_cast<DATATYPE>(static_cast<MLdouble>(*toPt_)*scaleDbl + shiftDbl);
703  }
704  }
705  }
706  }
707  }
708  }
709  }
710  } // if (!intersection.isEmpty())
711  } // else
712  } // if (getDataType()==typedFromImg.getDataType())
713 
714  // Images have different data type:
715  //---------------------------------
716  else{
717  // Copy overlap of both subimages and copy only if it is not empty.
718  const SubImageBox intersection = SubImageBox::intersect(typedFromImg.getBox(),getBox());
719  if (!intersection.isEmpty()){
720 
721  // Check data pointers and print errors if necessary.
722  _ML_CHECK_SUBIMAGE_DATA_POINTERS(typedFromImg.getData(), getData());
723 
724  ImageVector p;
725  const FROM_DATATYPE *fromPt = nullptr;
726  DATATYPE *toPt = nullptr;
727 
728  // Traverse all 6 dimensions.
729  for (p.u=intersection.v1.u; p.u<=intersection.v2.u; ++p.u){
730  for (p.t=intersection.v1.t; p.t<=intersection.v2.t; ++p.t){
731  for (p.c=intersection.v1.c; p.c<=intersection.v2.c; ++p.c){
732  for (p.z=intersection.v1.z; p.z<=intersection.v2.z; ++p.z){
733  for (p.y=intersection.v1.y; p.y<=intersection.v2.y; ++p.y){
734 
735  // Get start position to each slice of data.
736  const ImageVector pos(intersection.v1.x,p.y,p.z,p.c,p.t,p.u);
737  fromPt = typedFromImg.getImagePointer(pos);
738  toPt = getImagePointer(pos);
739  const MLint startX = intersection.v1.x;
740  const MLint endX = intersection.v2.x;
741 
742  if (!isFDTScalarType){
743  // When we work with extended types we must avoid to change to double during calculations since
744  // that causes information loss. In normal case we remain in double.
745  for (p.x = startX; p.x <= endX; ++p.x, ++fromPt, ++toPt){
746  *toPt=static_cast<DATATYPE>(static_cast<FROM_DATATYPE>(*fromPt)*scaleDbl + shiftDbl);
747  }
748  }
749  else{
750  for (p.x = startX; p.x <= endX; ++p.x, ++fromPt, ++toPt){
751  *toPt=static_cast<DATATYPE>(static_cast<MLdouble>(*fromPt)*scaleDbl + shiftDbl);
752  }
753  }
754  }
755  }
756  }
757  }
758  } // for (p.u)
759 
760  } // if (!intersection.isEmpty())
761 
762  } // else of if (getDataType()==typedFromImg.getDataType())
763  }
764 
765 
767 
768 
769  //-------------------------------------------------------------------------------------------
772  //-------------------------------------------------------------------------------------------
773 
774  //---------------------------------------------------------------------------
776  //---------------------------------------------------------------------------
777  inline void fill(DATATYPE value)
778  {
779  ML_CHECK_THROW(_data);
780 
781  const DATATYPE* dataEnd = static_cast<DATATYPE*>(_data) + getNumVoxels();
782 
783  for (DATATYPE* i = static_cast<DATATYPE*>(_data); i<dataEnd; ++i){ *i=value; }
784  };
785 
786 
787  //-------------------------------------------------------------------------------------------
793  //-------------------------------------------------------------------------------------------
794  inline void fillBordersWithValue(const SubImageBox& box, DATATYPE fillValue)
795  {
796  SubImage::fillBordersWithTypeData(box, reinterpret_cast<const MLTypeData*>(&fillValue));
797  }
798 
799  //-------------------------------------------------------------------------------------------
802  //-------------------------------------------------------------------------------------------
803  inline void fillInvalidRegionWithValue(DATATYPE value) {
804  fillBordersWithValue(getValidRegion(), value);
805  }
806 
807  //-------------------------------------------------------------------------------------------
811  //-------------------------------------------------------------------------------------------
813  fillBordersWithBorderValues(getValidRegion());
814  }
815 
817 };
818 
819 //---------------------------------------------------------------------------
821 //---------------------------------------------------------------------------
822 template <typename DATATYPE>
824 
825 protected:
826 
828  _data = const_cast<DATATYPE*>(subImage.getData());
829  _subImageOffset = subImage.getBox().v1;
830  _stride = subImage.getStride();
831  _cursor = _data;
832  }
833 
834 public:
835 
836  //---------------------------------------------------------------------------
839  //---------------------------------------------------------------------------
842  inline void setSubImagePosition(const ImageVector& position) { _cursor = _data+ImageVector::dot(position,_stride); }
845  inline void setSubImagePosition(MLint x, MLint y, MLint z) { _cursor = _data+_stride.x*x+_stride.y*y+_stride.z*z; }
848  inline void setImagePosition(const ImageVector& position) { _cursor = _data + _ML_TSUBIMG_SUBDOT6(position,_subImageOffset,_stride); }
851  inline void setImagePosition(MLint x, MLint y, MLint z) { _cursor = _data+ + _ML_TSUBIMG_SUBDOT3(x,y,z,_subImageOffset,_stride); }
853  inline void setPosition(const DATATYPE *pointer) { _cursor = const_cast<DATATYPE*>(pointer); }
855  inline void moveByOffset(const ImageVector& offset) { _cursor += ImageVector::dot(offset,_stride); }
857  inline void moveByOffset(MLint x, MLint y, MLint z) { _cursor += _stride.x*x+_stride.y*y+_stride.z*z; }
859  inline void moveX() { _cursor += _stride.x; }
861  inline void moveY() { _cursor += _stride.y; }
863  inline void moveZ() { _cursor += _stride.z; }
865  inline void moveC() { _cursor += _stride.c; }
867  inline void moveT() { _cursor += _stride.t; }
869  inline void moveU() { _cursor += _stride.u; }
871  inline void reverseMoveX() { _cursor -= _stride.x; }
873  inline void reverseMoveY() { _cursor -= _stride.y; }
875  inline void reverseMoveZ() { _cursor -= _stride.z; }
877  inline void reverseMoveC() { _cursor -= _stride.c; }
879  inline void reverseMoveT() { _cursor -= _stride.t; }
881  inline void reverseMoveU() { _cursor -= _stride.u; }
882 
884 
885  //---------------------------------------------------------------------------
888  // Note: All these functions do not need explicit 64-bit arithmetic, as
889  // pointer arithmetic always moves from valid address area to another
890  // valid address area even on 32-bit systems, and calculations do not fall
891  // outside valid ranges.
892  //---------------------------------------------------------------------------
894  inline DATATYPE getValue() const { return *(_cursor); }
895 
897  inline DATATYPE getValueWithOffset(const ImageVector& offset) const { return *(_cursor+ImageVector::dot(offset,_stride)); }
898 
900  inline DATATYPE getValueWithOffset(MLint dx, MLint dy, MLint dz) const { return *(_cursor+_stride.x*dx+_stride.y*dy+_stride.z*dz); }
901 
903 
904 protected:
906  DATATYPE* _data;
912  DATATYPE* _cursor;
913 };
914 
915 //---------------------------------------------------------------------------
918 //---------------------------------------------------------------------------
919 template <typename DATATYPE>
920 class ConstTSubImageCursor : public TSubImageCursorBase<DATATYPE> {
921 
923 
924 public:
925  ConstTSubImageCursor(const TSubImage<DATATYPE>& subImage) : TSubImageCursorBase<DATATYPE>(subImage) {
926  }
927 
928  //---------------------------------------------------------------------------
933  inline const DATATYPE* getPointer() const { return T::_cursor; }
935  inline const DATATYPE* getPointerWithOffset(const ImageVector& offset) const { return T::_cursor+ImageVector::dot(offset,T::_stride); }
937  inline const DATATYPE* getPointerWithOffset(MLint dx, MLint dy, MLint dz) const { return (T::_cursor+T::_stride.x*dx+T::_stride.y*dy+T::_stride.z*dz); }
939 };
940 
941 //---------------------------------------------------------------------------
944 //---------------------------------------------------------------------------
945 template <typename DATATYPE>
946 class TSubImageCursor : public TSubImageCursorBase<DATATYPE> {
947 
949 
950 public:
951 
952  TSubImageCursor(TSubImage<DATATYPE>& subImage) : TSubImageCursorBase<DATATYPE>(subImage) {
953  }
954 
955  //---------------------------------------------------------------------------
960  inline DATATYPE* getPointer() const { return T::_cursor; }
962  inline DATATYPE* getPointerWithOffset(const ImageVector& offset) const { return T::_cursor+ImageVector::dot(offset,T::_stride); }
964  inline DATATYPE* getPointerWithOffset(MLint dx, MLint dy, MLint dz) const { return (T::_cursor+T::_stride.x*dx+T::_stride.y*dy+T::_stride.z*dz); }
966 
967  //---------------------------------------------------------------------------
970  // Note: All these functions do not need explicit 64-bit arithmetic, because
971  // pointer arithmetic always moves from valid address area to another
972  // valid address area even on 32-bit systems, and calculations do not fall
973  // outside valid ranges.
974  //---------------------------------------------------------------------------
976  inline void setValue(DATATYPE value) const { *(T::_cursor) = value; }
978  inline void setValueWithOffset(const ImageVector& offset, DATATYPE value) const { *(T::_cursor+ImageVector::dot(offset,T::_stride))=value; }
980  inline void setValueWithOffset(MLint dx, MLint dy, MLint dz, DATATYPE value) const { *(T::_cursor+T::_stride.x*dx+T::_stride.y*dy+T::_stride.z*dz)=value; }
982 };
983 
984 //-------------------------------------------------------------------------
987 //-------------------------------------------------------------------------
988 template <typename DATATYPE>
989 class TSubImageWithCursor : public TSubImage<DATATYPE>
990 {
991  typedef TSubImage<DATATYPE> T;
992 
993 public:
995  TSubImageWithCursor():TSubImage<DATATYPE>(), _cursor(nullptr)
996  {
997  }
999  TSubImageWithCursor(const TSubImage<DATATYPE>& subImage):TSubImage<DATATYPE>(subImage), _cursor(nullptr)
1000  {
1001  }
1002 
1004  TSubImageWithCursor(const SubImage& subImage):TSubImage<DATATYPE>(subImage), _cursor(nullptr)
1005  {
1006  }
1007 
1009  TSubImageWithCursor(const TSubImageWithCursor& subImage):TSubImage<DATATYPE>(subImage),_cursor(subImage._cursor)
1010  {
1011  }
1012 
1016  {
1018  _cursor = tSubImg._cursor;
1019  return *this;
1020  }
1021 
1022  //---------------------------------------------------------------------------
1025  //---------------------------------------------------------------------------
1028  inline void setCursorSubImagePosition(const ImageVector& position) { _cursor = static_cast<DATATYPE*>(T::_data)+ImageVector::dot(position,T::_stride); }
1031  inline void setCursorSubImagePosition(MLint x, MLint y, MLint z) { _cursor = static_cast<DATATYPE*>(T::_data)+T::_stride.x*x+T::_stride.y*y+T::_stride.z*z; }
1034  inline void setCursorImagePosition(const ImageVector& position) { _cursor = static_cast<DATATYPE*>(T::_data)+ _ML_TSUBIMG_SUBDOT6(position, T::_box.v1 ,T::_stride); }
1037  inline void setCursorImagePosition(MLint x, MLint y, MLint z) { _cursor = static_cast<DATATYPE*>(T::_data)+ _ML_TSUBIMG_SUBDOT3(x,y,z, T::_box.v1 ,T::_stride); }
1039  inline void setCursorPosition(const DATATYPE* pointer) { _cursor = const_cast<DATATYPE*>(pointer); }
1041  inline void moveCursorByOffset(const ImageVector& offset) { _cursor += ImageVector::dot(offset,T::_stride); }
1043  inline void moveCursorByOffset(MLint x, MLint y, MLint z) { _cursor += T::_stride.x*x+T::_stride.y*y+T::_stride.z*z; }
1045  inline void moveCursorX() { _cursor += T::_stride.x; }
1047  inline void moveCursorY() { _cursor += T::_stride.y; }
1049  inline void moveCursorZ() { _cursor += T::_stride.z; }
1051  inline void moveCursorC() { _cursor += T::_stride.c; }
1053  inline void moveCursorT() { _cursor += T::_stride.t; }
1055  inline void moveCursorU() { _cursor += T::_stride.u; }
1057  inline void reverseMoveCursorX() { _cursor -= T::_stride.x; }
1059  inline void reverseMoveCursorY() { _cursor -= T::_stride.y; }
1061  inline void reverseMoveCursorZ() { _cursor -= T::_stride.z; }
1063  inline void reverseMoveCursorC() { _cursor -= T::_stride.c; }
1065  inline void reverseMoveCursorT() { _cursor -= T::_stride.t; }
1067  inline void reverseMoveCursorU() { _cursor -= T::_stride.u; }
1068 
1070 
1071  //---------------------------------------------------------------------------
1074  // Note: All these functions do not need explicit 64-bit arithmetic, because
1075  // pointer arithmetic always goes from valid address area to another
1076  // valid address area even on 32-bit systems, and calculations do not fall
1077  // outside valid ranges.
1078  //---------------------------------------------------------------------------
1080  inline DATATYPE getCursorValue() const { return *(_cursor); }
1082  inline DATATYPE getCursorValueWithOffset(const ImageVector& offset) const { return *(_cursor+ImageVector::dot(offset,T::_stride)); }
1084  inline DATATYPE getCursorValueWithOffset(MLint dx, MLint dy, MLint dz) const { return *(_cursor+T::_stride.x*dx+T::_stride.y*dy+T::_stride.z*dz); }
1085 
1087 
1088  //---------------------------------------------------------------------------
1093  inline DATATYPE* getCursorPointer() const { return _cursor; }
1095  inline DATATYPE* getCursorPointerWithOffset(const ImageVector& offset) const { return _cursor+ImageVector::dot(offset,T::_stride); }
1097  inline DATATYPE* getCursorPointerWithOffset(MLint dx, MLint dy, MLint dz) const { return (_cursor+T::_stride.x*dx+T::_stride.y*dy+T::_stride.z*dz); }
1099 
1100  //---------------------------------------------------------------------------
1103  // Note: All these functions do not need explicit 64-bit arithmetic, because
1104  // pointer arithmetic always goes from valid address area to another
1105  // valid address area even on 32-bit systems, and calculations do not fall
1106  // outside valid ranges.
1107  //---------------------------------------------------------------------------
1109  inline void setCursorValue(DATATYPE value) { *(_cursor) = value; }
1111  inline void setCursorValueWithOffset(const ImageVector& offset, DATATYPE value) { *(_cursor+ImageVector::dot(offset,T::_stride))=value; }
1113  inline void setCursorValueWithOffset(MLint dx, MLint dy, MLint dz, DATATYPE value) { *(_cursor+T::_stride.x*dx+T::_stride.y*dy+T::_stride.z*dz)=value; }
1114 
1116 
1117 private:
1119  DATATYPE* _cursor;
1120 };
1121 
1122 //---------------------------------------------------------------------------
1133 //---------------------------------------------------------------------------
1134 template <typename T>
1136 {
1137  // Check whether template type and real data type match if there is valid data.
1138  if (subImg.getData() && !TypeTraits<T>::matches(subImg.getDataType()) )
1139  {
1140  ML_PRINT_FATAL_ERROR("tsubimage_cast", ML_BAD_DATA_TYPE,
1141  "Mismatch of data type between argument and template typename.");
1142  }
1143  return *(static_cast<TSubImage<T>* >(&subImg));
1144 }
1145 
1146 template <typename T>
1147 const TSubImage<T>& tsubimage_cast(const SubImage& subImg)
1148 {
1149  // Check whether template type and real data type match if there is valid data.
1150  if (subImg.getData() && !TypeTraits<T>::matches(subImg.getDataType()) )
1151  {
1152  ML_PRINT_FATAL_ERROR("tsubimage_cast", ML_BAD_DATA_TYPE,
1153  "Mismatch of data type between argument and template typename.");
1154  }
1155  return *(static_cast<const TSubImage<T>* >(&subImg));
1156 }
1157 
1158 template <typename T>
1160 {
1161  // Check whether template type and real data type match if there is valid data.
1162  if (subImg->getData() && !TypeTraits<T>::matches(subImg->getDataType()) )
1163  {
1164  ML_PRINT_FATAL_ERROR("tsubimage_cast", ML_BAD_DATA_TYPE,
1165  "Mismatch of data type between argument and template typename.");
1166  }
1167  return static_cast<TSubImage<T>* >(subImg);
1168 }
1169 
1170 template <typename T>
1171 const TSubImage<T>* tsubimage_cast(const SubImage* subImg)
1172 {
1173  // Check whether template type and real data type match if there is valid data.
1174  if (subImg->getData() && !TypeTraits<T>::matches(subImg->getDataType()) )
1175  {
1176  ML_PRINT_FATAL_ERROR("tsubimage_cast", ML_BAD_DATA_TYPE,
1177  "Mismatch of data type between argument and template typename.");
1178  }
1179  return static_cast<const TSubImage<T>* >(subImg);
1180 }
1181 
1183 
1184 
1185 ML_END_NAMESPACE
1186 
1187 namespace std {
1188 
1189  //---------------------------------------------------------------------------
1190  // Debug printing for TSubImage.
1191  //---------------------------------------------------------------------------
1192 
1195  template <typename DATATYPE>
1196  inline ostream &operator<<(ostream &ostr, const ML_NAMESPACE::TSubImage<DATATYPE> &v)
1197  {
1198  // Get box of subimage and traverse all of its voxels.
1199  const ML_NAMESPACE::SubImageBox& box = v.getBox();
1201  for (p.u=box.v1.u; p.u<=box.v2.u; ++p.u){
1202  for (p.t=box.v1.t; p.t<=box.v2.t; ++p.t){
1203  for (p.c=box.v1.c; p.c<=box.v2.c; ++p.c){
1204  for (p.z=box.v1.z; p.z<=box.v2.z; ++p.z){
1205  for (p.y=box.v1.y; p.y<=box.v2.y; ++p.y){
1206  // Print row of voxels after a single row start position.
1207  p.x = box.v1.x;
1208  ostr << p << ": ";
1209  for (; p.x<=box.v2.x; p.x++){
1210  ostr << v.getImageValue(p) << " ";
1211  }
1212  ostr << std::endl;
1213  }
1214  }
1215  }
1216  }
1217  }
1218  return ostr;
1219  }
1220 
1221 }
1222 
1223 #ifdef _MSC_VER
1224 #pragma warning(pop)
1225 #endif
1226 
1227 
1228 #endif //of __mlTSubImage_H
1229 
1230 
1231 
@ T
Definition: SoKeyGrabber.h:71
Predeclaration for const cursor.
Definition: mlTSubImage.h:920
ConstTSubImageCursor(const TSubImage< DATATYPE > &subImage)
Definition: mlTSubImage.h:925
const DATATYPE * getPointer() const
Definition: mlTSubImage.h:933
const DATATYPE * getPointerWithOffset(const ImageVector &offset) const
Returns the cursor position of the voxel computed from the current cursor shifted by offset.
Definition: mlTSubImage.h:935
const DATATYPE * getPointerWithOffset(MLint dx, MLint dy, MLint dz) const
Returns the cursor position of the voxel computed from the current cursor shifted by (dx,...
Definition: mlTSubImage.h:937
This class manages/represents a rectangular 6D image region that is organized linearly in memory.
Definition: mlSubImage.h:75
void * getData() const
Returns the memory address of the memory managed by the subimage.
Definition: mlSubImage.h:372
MLDataType getDataType() const
Returns the type of image data.
Definition: mlSubImage.h:288
ImageVector getStride() const
Returns a stride vector to address the memory efficiently.
Definition: mlSubImage.h:264
const SubImageBox & getBox() const
Returns the box describing the origin/extent of the subimage.
Definition: mlSubImage.h:230
ImageVector getSourceImageExtent() const
Returns the image extent of the source image that was used to create this SubImage.
Definition: mlSubImage.h:241
void set(const ComponentType v=0)
Sets all components to v or - if v is not specified - to 0.
DT getScale() const
Returns the scale constant of the transformation y=scale*x+offset.
ReorderMode getReorderMode() const
Returns the reorder mode.
DT getShift() const
Returns the addition constant of the transformation y=scale*x+shift.
VectorType v1
Corner v1 of the subimage region (included in region).
Definition: mlSubImageBox.h:63
VectorType v2
Corner v2 of the subimage region (also included in region!).
Definition: mlSubImageBox.h:69
intT getNumVoxels() const
Returns number of voxels in the subimage region, i.e., the product of all extents if this is not empt...
bool isEmpty() const
Returns true if subimage region is empty, i.e., if any of the components of v1 is greater than the co...
Base class for all TSubImage Cursors.
Definition: mlTSubImage.h:823
void reverseMoveC()
Moves the cursor backward in c direction.
Definition: mlTSubImage.h:877
void moveT()
Moves the cursor forward in t direction.
Definition: mlTSubImage.h:867
void reverseMoveX()
Moves the cursor backward in x direction.
Definition: mlTSubImage.h:871
void moveZ()
Moves the cursor forward in z direction.
Definition: mlTSubImage.h:863
void setPosition(const DATATYPE *pointer)
Sets the cursor to the given pointer where the pointer is the memory address of the voxel.
Definition: mlTSubImage.h:853
void reverseMoveY()
Moves the cursor backward in y direction.
Definition: mlTSubImage.h:873
DATATYPE getValue() const
Returns the voxel value at cursor position.
Definition: mlTSubImage.h:894
void reverseMoveT()
Moves the cursor backward in t direction.
Definition: mlTSubImage.h:879
ImageVector _stride
Stride for the subimage.
Definition: mlTSubImage.h:910
void moveU()
Moves the cursor forward in u direction.
Definition: mlTSubImage.h:869
void setSubImagePosition(MLint x, MLint y, MLint z)
Sets the cursor to the given 3D position (x, y, z) relative to the origin of the subimage region.
Definition: mlTSubImage.h:845
DATATYPE getValueWithOffset(MLint dx, MLint dy, MLint dz) const
Return the voxel value at (cursor position + (dx, dy, dz))
Definition: mlTSubImage.h:900
void moveX()
Moves the cursor forward in x direction.
Definition: mlTSubImage.h:859
DATATYPE getValueWithOffset(const ImageVector &offset) const
Returns the voxel value at (cursor position + offset).
Definition: mlTSubImage.h:897
ImageVector _subImageOffset
SubImage offset in original image.
Definition: mlTSubImage.h:908
DATATYPE * _data
SubImage data.
Definition: mlTSubImage.h:906
void reverseMoveZ()
Moves the cursor backward in z direction.
Definition: mlTSubImage.h:875
void setImagePosition(const ImageVector &position)
Sets the cursor to the given 6D position relative to the origin of the complete image region.
Definition: mlTSubImage.h:848
void moveByOffset(const ImageVector &offset)
Moves the cursor to cursor position + offset.
Definition: mlTSubImage.h:855
DATATYPE * _cursor
Cursor address for image data access.
Definition: mlTSubImage.h:912
void reverseMoveU()
Moves the cursor backward in u direction.
Definition: mlTSubImage.h:881
TSubImageCursorBase(const TSubImage< DATATYPE > &subImage)
Definition: mlTSubImage.h:827
void moveY()
Moves the cursor forward in y direction.
Definition: mlTSubImage.h:861
void setSubImagePosition(const ImageVector &position)
Sets the cursor to the given position relative to the origin of the subimage region.
Definition: mlTSubImage.h:842
void moveByOffset(MLint x, MLint y, MLint z)
Moves the cursor to cursor position + (x, y, z).
Definition: mlTSubImage.h:857
void setImagePosition(MLint x, MLint y, MLint z)
Sets the cursor to the given 3D position (x, y, z) relative to the origin of the complete image regio...
Definition: mlTSubImage.h:851
void moveC()
Moves the cursor forward in c direction.
Definition: mlTSubImage.h:865
Predeclaration for cursor.
Definition: mlTSubImage.h:946
void setValueWithOffset(MLint dx, MLint dy, MLint dz, DATATYPE value) const
Sets the voxel value at (cursor position + (dx, dy, dz)) to value.
Definition: mlTSubImage.h:980
TSubImageCursor(TSubImage< DATATYPE > &subImage)
Definition: mlTSubImage.h:952
void setValueWithOffset(const ImageVector &offset, DATATYPE value) const
Sets the voxel value at (cursor position + offset) to value.
Definition: mlTSubImage.h:978
void setValue(DATATYPE value) const
Sets the voxel value at the cursor position to value.
Definition: mlTSubImage.h:976
DATATYPE * getPointerWithOffset(MLint dx, MLint dy, MLint dz) const
Returns the cursor position of the voxel computed from the current cursor shifted by (dx,...
Definition: mlTSubImage.h:964
DATATYPE * getPointerWithOffset(const ImageVector &offset) const
Returns the cursor position of the voxel computed from the current cursor shifted by offset.
Definition: mlTSubImage.h:962
DATATYPE * getPointer() const
Definition: mlTSubImage.h:960
A class that offers a TSubImage with a TSubImageCursor.
Definition: mlTSubImage.h:990
void setCursorValue(DATATYPE value)
Sets the voxel value at the cursor position to value.
Definition: mlTSubImage.h:1109
void reverseMoveCursorC()
Moves the cursor backward in c direction.
Definition: mlTSubImage.h:1063
void moveCursorT()
Moves the cursor forward in t direction.
Definition: mlTSubImage.h:1053
DATATYPE * getCursorPointer() const
Definition: mlTSubImage.h:1093
void moveCursorByOffset(const ImageVector &offset)
Moves the cursor to cursor position + offset.
Definition: mlTSubImage.h:1041
void setCursorImagePosition(MLint x, MLint y, MLint z)
Sets the cursor to the given 3D position (x, y, z) relative to the origin of the complete image regio...
Definition: mlTSubImage.h:1037
DATATYPE getCursorValue() const
Returns the voxel value at the cursor position.
Definition: mlTSubImage.h:1080
void reverseMoveCursorU()
Moves the cursor backward in u direction.
Definition: mlTSubImage.h:1067
void reverseMoveCursorY()
Moves the cursor backward in y direction.
Definition: mlTSubImage.h:1059
DATATYPE * getCursorPointerWithOffset(MLint dx, MLint dy, MLint dz) const
Returns the cursor pointer of the voxel computed from the current cursor shifted by (dx,...
Definition: mlTSubImage.h:1097
DATATYPE getCursorValueWithOffset(MLint dx, MLint dy, MLint dz) const
Returns the voxel value at (cursor position + (dx, dy, dz))
Definition: mlTSubImage.h:1084
void reverseMoveCursorX()
Moves the cursor backward in x direction.
Definition: mlTSubImage.h:1057
void moveCursorByOffset(MLint x, MLint y, MLint z)
Moves the cursor to cursor position + (x, y, z).
Definition: mlTSubImage.h:1043
TSubImageWithCursor(const TSubImage< DATATYPE > &subImage)
Constructor with TSubImage.
Definition: mlTSubImage.h:999
void moveCursorZ()
Moves the cursor forward in z direction.
Definition: mlTSubImage.h:1049
void reverseMoveCursorZ()
Moves the cursor backward in z direction.
Definition: mlTSubImage.h:1061
void moveCursorC()
Moves the cursor forward in c direction.
Definition: mlTSubImage.h:1051
void reverseMoveCursorT()
Moves the cursor backward in t direction.
Definition: mlTSubImage.h:1065
void setCursorValueWithOffset(const ImageVector &offset, DATATYPE value)
Sets the voxel value at (cursor position + offset) to value.
Definition: mlTSubImage.h:1111
void setCursorImagePosition(const ImageVector &position)
Sets the cursor to the given 6D position relative to the origin of the complete image region.
Definition: mlTSubImage.h:1034
void setCursorPosition(const DATATYPE *pointer)
Sets the cursor to the given pointer where pointer is the memory address of the voxel.
Definition: mlTSubImage.h:1039
DATATYPE * getCursorPointerWithOffset(const ImageVector &offset) const
Returns the cursor pointer of the voxel computed from the current cursor shifted by offset.
Definition: mlTSubImage.h:1095
TSubImageWithCursor & operator=(const TSubImageWithCursor< DATATYPE > &tSubImg)
Assignment operator to get an identical copy.
Definition: mlTSubImage.h:1015
void moveCursorY()
Moves the cursor forward in y direction.
Definition: mlTSubImage.h:1047
void moveCursorX()
Moves the cursor forward in x direction.
Definition: mlTSubImage.h:1045
TSubImageWithCursor(const TSubImageWithCursor &subImage)
Constructor with TSubImageWithCursor.
Definition: mlTSubImage.h:1009
TSubImageWithCursor(const SubImage &subImage)
Constructor with SubImage.
Definition: mlTSubImage.h:1004
void moveCursorU()
Moves the cursor forward in u direction.
Definition: mlTSubImage.h:1055
DATATYPE getCursorValueWithOffset(const ImageVector &offset) const
Returns the voxel value at (cursor position + offset)
Definition: mlTSubImage.h:1082
void setCursorSubImagePosition(MLint x, MLint y, MLint z)
Sets the cursor to the given 3D position (x, y, z) relative to the origin of the subimage region.
Definition: mlTSubImage.h:1031
void setCursorSubImagePosition(const ImageVector &position)
Sets the cursor to the given position relative to the origin of the subimage region.
Definition: mlTSubImage.h:1028
TSubImageWithCursor()
Default constructor.
Definition: mlTSubImage.h:995
void setCursorValueWithOffset(MLint dx, MLint dy, MLint dz, DATATYPE value)
Sets voxel value at (cursor position + (dx, dy,dz)) to value.
Definition: mlTSubImage.h:1113
This template class manages/represents a rectangular 6D image region in memory that is organized line...
Definition: mlTSubImage.h:110
TSubImage(const SubImage &subImage)
Constructor to build a typed subimage from an untyped subImage.
Definition: mlTSubImage.h:169
DATATYPE getSubImageValue(MLint x, MLint y, MLint z) const
Returns the voxel value at the given position (x, y, z) where the position is relative to the origin ...
Definition: mlTSubImage.h:374
void copySubImageTyped(const TSubImage< FROM_DATATYPE > &typedFromImg, const ScaleShiftData &scaleShiftData)
Copies image data from the subimage fromImg into the overlapping region of this subimage.
Definition: mlTSubImage.h:590
TSubImage(const TSubImage< DATATYPE > &typedSubImage)
Copy constructor to get an identical copy.
Definition: mlTSubImage.h:194
void copySubImageReorderColorPlanesToInterleaved(const TSubImage< FROM_DATATYPE > &typedFromImage, const ScaleShiftData &scaleShiftData)
Implements special case for void copySubImageTyped(const TSubImage<FROM_DATATYPE> &typedFromImg,...
Definition: mlTSubImage.h:498
void setSubImageValue(MLint x, MLint y, DATATYPE value)
Sets the voxel value at the given position(x, y) to the given value where the position is relative to...
Definition: mlTSubImage.h:361
DATATYPE getImageValue(MLint x, MLint y) const
Returns the 2D voxel value from the given position (x, y).
Definition: mlTSubImage.h:392
TSubImage(const SubImageBox &box, MLDataType dataType, void *data)
Constructor for an image region with location/extent box with data type dataType (must fit to DATATYP...
Definition: mlTSubImage.h:137
const DATATYPE * getImagePointer(const ImageVector &position) const
Returns a pointer to voxel data of image voxel at 6D position position relative to the origin of the ...
Definition: mlTSubImage.h:253
void setImageValue(const ImageVector &position, DATATYPE value)
Sets the 6D voxel at the given position to the given value.
Definition: mlTSubImage.h:379
DATATYPE getSubImageValue(MLint x, MLint y) const
Returns the voxel value at position (x, y) where the position is relative to the origin of the subima...
Definition: mlTSubImage.h:365
const DATATYPE * getImagePointer(MLint x, MLint y, MLint z) const
Returns a pointer to voxel data of image voxel at 3D position p=(x, y, z) relative to the origin of t...
Definition: mlTSubImage.h:261
ConstTSubImageCursor< DATATYPE > ConstCursor
A read-only cursor.
Definition: mlTSubImage.h:120
~TSubImage() override=default
Virtual destructor to suppress compiler warnings.
void fill(DATATYPE value)
Sets all voxel values in subimage to value.
Definition: mlTSubImage.h:777
TSubImage & operator=(const TSubImage< DATATYPE > &typedSubImage)
Assignment operator to get an identical copy.
Definition: mlTSubImage.h:204
ImageVector convertPointerToImagePosition(DATATYPE *pointer) const
Returns the 6D voxel coordinates corresponding to the memory address pointer.
Definition: mlTSubImage.h:311
DATATYPE getImageValue(MLint x, MLint y, MLint z) const
Returns the 3D voxel value from given position (x, y, z).
Definition: mlTSubImage.h:401
TSubImageCursor< DATATYPE > Cursor
A read/write cursor.
Definition: mlTSubImage.h:118
ImageVector convertPointerToSubImagePosition(DATATYPE *pointer) const
Returns the 6D voxel coordinates corresponding to the memory address pointer.
Definition: mlTSubImage.h:274
TSubImage()
Default constructor to build a typed subimage (with an empty box) from scratch.
Definition: mlTSubImage.h:152
DATATYPE getImageValue(const ImageVector &position) const
Returns the 6D voxel value from the given position.
Definition: mlTSubImage.h:383
DATATYPE * getSubImagePointer(const ImageVector &position)
Definition: mlTSubImage.h:234
void fillInvalidRegionWithValue(DATATYPE value)
Fills the invalid region (everything outside of getValidRegion()) with the given value.
Definition: mlTSubImage.h:803
DATATYPE * getImagePointer(MLint x, MLint y, MLint z)
Definition: mlTSubImage.h:262
DATATYPE ComponentType
A typedef to 'export' the type of voxels components.
Definition: mlTSubImage.h:115
void setImageValue(MLint x, MLint y, MLint z, DATATYPE value)
Sets the 3D voxel at the given position (x, y, z) to the given value.
Definition: mlTSubImage.h:397
void fillBordersWithValue(const SubImageBox &box, DATATYPE fillValue)
Fills all regions with fillValue that are not covered by box.
Definition: mlTSubImage.h:794
DATATYPE getSubImageValue(const ImageVector &position) const
Returns voxel value at the given position where position is relative to the origin of the subimage re...
Definition: mlTSubImage.h:356
void setSubImageValue(const ImageVector &position, DATATYPE value)
Sets the voxel value at the given position to the given value where position is relative to the origi...
Definition: mlTSubImage.h:351
MLint calculateMinMax(DATATYPE &minValue, DATATYPE &maxValue, const SubImageBox *const validBox=nullptr) const
Scans subimage and determines the minimum and maximum values of the region that is part of subimage b...
Definition: mlTSubImage.h:420
void convertPointerToSubImagePosition(DATATYPE *pointer, MLint *x, MLint *y, MLint *z) const
Returns the 3D voxel coordinates corresponding to the memory address pointer.
Definition: mlTSubImage.h:282
DATATYPE & operator[](const ImageVector &position)
Reference access to voxel value at the given position.
Definition: mlTSubImage.h:346
DATATYPE * getSubImagePointer(MLint x, MLint y, MLint z)
Definition: mlTSubImage.h:246
DATATYPE * getData()
Definition: mlTSubImage.h:218
const DATATYPE * getData() const
Returns the memory address of the image region. Overloads methods from SubImage.
Definition: mlTSubImage.h:217
const DATATYPE * getSubImagePointer(const ImageVector &position) const
Returns a pointer to voxel data of image voxel at the 6D position relative to the origin of the subim...
Definition: mlTSubImage.h:233
void setImageValue(MLint x, MLint y, DATATYPE value)
Sets the 2D voxel at the given position (x, y) to the the given value.
Definition: mlTSubImage.h:388
void setSubImageValue(MLint x, MLint y, MLint z, DATATYPE value)
Sets the voxel value at the given position (x, y, z) to the given value where the position is relativ...
Definition: mlTSubImage.h:370
const DATATYPE * getSubImagePointer(MLint x, MLint y, MLint z) const
Returns a pointer to voxel data of image voxel at 3D position p=(x, y, z) relative to the origin of t...
Definition: mlTSubImage.h:245
const DATATYPE & operator[](const ImageVector &position) const
Constant reference access to voxel value at the given position.
Definition: mlTSubImage.h:340
void convertPointerToImagePosition(DATATYPE *pointer, MLint *x, MLint *y, MLint *z) const
Returns the 3D voxel coordinates corresponding to the memory address pointer.
Definition: mlTSubImage.h:320
DATATYPE * getImagePointer(const ImageVector &position)
Definition: mlTSubImage.h:254
void fillInvalidRegionWithBorderValues()
Fills the invalid region (i.e., everything outside of getValidRegion() ) with the values on the borde...
Definition: mlTSubImage.h:812
ComponentType c
Color component of the vector.
Definition: mlImageVector.h:65
ComponentType t
Time component of the vector.
Definition: mlImageVector.h:67
ComponentType u
Unit/Modality/User component of the vector.
Definition: mlImageVector.h:69
ComponentType z
Z component of the vector.
Definition: mlImageVector.h:63
ComponentType x
X component of the vector.
Definition: mlImageVector.h:59
ComponentType y
Y component of the vector.
Definition: mlImageVector.h:61
TVector< TVectorBase > getStrides(const ComponentType offset=1) const
Interprets the vector as image extension and returns a stride vector.
TVector< TVectorBase > getVectorPosition(ComponentType offsetPos) const
Interprets the vector as a stride vector of an image and returns the offset position offsetPos from t...
MLEXPORT size_t MLSizeOf(MLDataType dataType)
Returns the size of the data type dataType in bytes.
#define ML_INVALID_DATA_TYPE
Defines an invalid MLDataType.
Definition: mlTypeDefs.h:613
bool MLValuesAreEqual(MLint8 a, MLint8 b, MLint8)
Returns true if values are equal (numerically safely compared); otherwise, it returns false.
MLint32 MLDataType
MLDataType.
Definition: mlTypeDefs.h:596
#define ML_BAD_DATA_TYPE
A wrong or unexpected data type has been passed to an algorithm, which often is a programming error.
Definition: mlTypeDefs.h:782
#define ML_PRINT_FATAL_ERROR(FUNC_NAME, REASON, HANDLING)
Like ML_PRINT_FATAL_ERROR_DUMP(FUNC_NAME, REASON, HANDLING, RT_OBJ) without a runtime object to be du...
#define ML_CHECK_THROW(x)
Definition: mlErrorMacros.h:89
MLEXPORT std::ostream & operator<<(std::ostream &s, const ml::Field &v)
Overloads the operator '<<' for stream output of Field objects.
#define _ML_TSUBIMG_SUBDOT6(pos, offset, stride)
Private helper macro for calculation of memory offset, calculates (pos-offset) * stride.
Definition: mlTSubImage.h:44
#define _ML_TSUBIMG_SUBDOT2(x, y, offset, stride)
Private helper macro for calculation of memory offset, calculates ((xy)-offset) * stride.
Definition: mlTSubImage.h:59
#define _ML_TSUBIMG_SUBDOT3(x, y, z, offset, stride)
Private helper macro for calculation of memory offset, calculates ((xyz)-offset) * stride.
Definition: mlTSubImage.h:53
#define _ML_CHECK_SUBIMAGE_DATA_POINTERS(FROM_PTR, TO_PTR)
Internal helper macro to check validity of data pointers of subimages.
Definition: mlTSubImage.h:482
MLint32 MLIsScalarTypePtr(const T *)
double MLdouble
Definition: mlTypeDefs.h:217
unsigned char MLTypeData
This is the pointer type used to point to the data of MLType data instances.
Definition: mlTypeDefs.h:1300
MLint64 MLint
A signed ML integer type with at least 64 bits used for index calculations on very large images even ...
Definition: mlTypeDefs.h:490
MLWEM_EXPORT void intersect(WEMTrianglePatch *inPatch1, WEMTrianglePatch *inPatch2, WEMTrianglePatch *outPatch, unsigned int outputMode, TriangulationModes triangulationMode, WEMVector< WEMCut > *cuts=nullptr)
Returns the intersection of the given patches.
TSubImageBox< MLint > SubImageBox
Defines the standard SubImageBox type used in the ML. Its size varies with the size of the MLint type...
TImageVector< MLint > ImageVector
Defines the standard ImageVector type that is used by the ML for indexing and coordinates.
const TSubImage< T > * tsubimage_cast(const SubImage *subImg)
Definition: mlTSubImage.h:1171
TypeTraits for scalar ML datatypes.
Definition: mlTypeTraits.h:52