ML 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
33ML_START_NAMESPACE
34
35
36
37
39template <typename DATATYPE> class TSubImageCursor;
41template <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//-------------------------------------------------------------------------
108template <typename DATATYPE>
109class TSubImage : public SubImage
110{
111
112public:
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.
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.
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//---------------------------------------------------------------------------
822template <typename DATATYPE>
824
825protected:
826
828 _data = const_cast<DATATYPE*>(subImage.getData());
829 _subImageOffset = subImage.getBox().v1;
830 _stride = subImage.getStride();
831 _cursor = _data;
832 }
833
834public:
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
904protected:
906 DATATYPE* _data;
912 DATATYPE* _cursor;
913};
914
915//---------------------------------------------------------------------------
918//---------------------------------------------------------------------------
919template <typename DATATYPE>
921
923
924public:
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//---------------------------------------------------------------------------
945template <typename DATATYPE>
946class TSubImageCursor : public TSubImageCursorBase<DATATYPE> {
947
949
950public:
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//-------------------------------------------------------------------------
988template <typename DATATYPE>
989class TSubImageWithCursor : public TSubImage<DATATYPE>
990{
991 typedef TSubImage<DATATYPE> T;
992
993public:
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
1117private:
1119 DATATYPE* _cursor;
1120};
1121
1122//---------------------------------------------------------------------------
1133//---------------------------------------------------------------------------
1134template <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
1146template <typename T>
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
1158template <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
1170template <typename T>
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
1185ML_END_NAMESPACE
1186
1187namespace 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();
1200 ML_NAMESPACE::ImageVector p;
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
Predeclaration for const cursor.
ConstTSubImageCursor(const TSubImage< DATATYPE > &subImage)
const DATATYPE * getPointerWithOffset(const ImageVector &offset) const
Returns the cursor position of the voxel computed from the current cursor shifted by offset.
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,...
const DATATYPE * getPointer() const
This class manages/represents a rectangular 6D image region that is organized linearly in memory.
Definition mlSubImage.h:75
const SubImageBox & getBox() const
Returns the box describing the origin/extent of the subimage.
Definition mlSubImage.h:230
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
void * getData() const
Returns the memory address of the memory managed by the subimage.
Definition mlSubImage.h:372
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).
VectorType v2
Corner v2 of the subimage region (also included in region!).
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.
void reverseMoveC()
Moves the cursor backward in c direction.
void moveT()
Moves the cursor forward in t direction.
void reverseMoveX()
Moves the cursor backward in x direction.
void moveZ()
Moves the cursor forward in z direction.
void setPosition(const DATATYPE *pointer)
Sets the cursor to the given pointer where the pointer is the memory address of the voxel.
void reverseMoveY()
Moves the cursor backward in y direction.
DATATYPE getValue() const
Returns the voxel value at cursor position.
void reverseMoveT()
Moves the cursor backward in t direction.
ImageVector _stride
Stride for the subimage.
void moveU()
Moves the cursor forward in u direction.
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.
DATATYPE getValueWithOffset(MLint dx, MLint dy, MLint dz) const
Return the voxel value at (cursor position + (dx, dy, dz))
void moveX()
Moves the cursor forward in x direction.
DATATYPE getValueWithOffset(const ImageVector &offset) const
Returns the voxel value at (cursor position + offset).
ImageVector _subImageOffset
SubImage offset in original image.
DATATYPE * _data
SubImage data.
void reverseMoveZ()
Moves the cursor backward in z direction.
void setImagePosition(const ImageVector &position)
Sets the cursor to the given 6D position relative to the origin of the complete image region.
void moveByOffset(const ImageVector &offset)
Moves the cursor to cursor position + offset.
DATATYPE * _cursor
Cursor address for image data access.
void reverseMoveU()
Moves the cursor backward in u direction.
TSubImageCursorBase(const TSubImage< DATATYPE > &subImage)
void moveY()
Moves the cursor forward in y direction.
void setSubImagePosition(const ImageVector &position)
Sets the cursor to the given position relative to the origin of the subimage region.
void moveByOffset(MLint x, MLint y, MLint z)
Moves the cursor to cursor position + (x, y, z).
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...
void moveC()
Moves the cursor forward in c direction.
Predeclaration for cursor.
DATATYPE * getPointerWithOffset(const ImageVector &offset) const
Returns the cursor position of the voxel computed from the current cursor shifted by offset.
DATATYPE * getPointer() const
void setValueWithOffset(MLint dx, MLint dy, MLint dz, DATATYPE value) const
Sets the voxel value at (cursor position + (dx, dy, dz)) to value.
TSubImageCursor(TSubImage< DATATYPE > &subImage)
void setValueWithOffset(const ImageVector &offset, DATATYPE value) const
Sets the voxel value at (cursor position + offset) to value.
void setValue(DATATYPE value) const
Sets the voxel value at the cursor position to value.
DATATYPE * getPointerWithOffset(MLint dx, MLint dy, MLint dz) const
Returns the cursor position of the voxel computed from the current cursor shifted by (dx,...
A class that offers a TSubImage with a TSubImageCursor.
void setCursorValue(DATATYPE value)
Sets the voxel value at the cursor position to value.
void reverseMoveCursorC()
Moves the cursor backward in c direction.
void moveCursorT()
Moves the cursor forward in t direction.
void moveCursorByOffset(const ImageVector &offset)
Moves the cursor to cursor position + offset.
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...
DATATYPE getCursorValue() const
Returns the voxel value at the cursor position.
void reverseMoveCursorU()
Moves the cursor backward in u direction.
void reverseMoveCursorY()
Moves the cursor backward in y direction.
DATATYPE getCursorValueWithOffset(MLint dx, MLint dy, MLint dz) const
Returns the voxel value at (cursor position + (dx, dy, dz))
void reverseMoveCursorX()
Moves the cursor backward in x direction.
void moveCursorByOffset(MLint x, MLint y, MLint z)
Moves the cursor to cursor position + (x, y, z).
TSubImageWithCursor(const TSubImage< DATATYPE > &subImage)
Constructor with TSubImage.
void moveCursorZ()
Moves the cursor forward in z direction.
void reverseMoveCursorZ()
Moves the cursor backward in z direction.
void moveCursorC()
Moves the cursor forward in c direction.
DATATYPE * getCursorPointerWithOffset(const ImageVector &offset) const
Returns the cursor pointer of the voxel computed from the current cursor shifted by offset.
void reverseMoveCursorT()
Moves the cursor backward in t direction.
void setCursorValueWithOffset(const ImageVector &offset, DATATYPE value)
Sets the voxel value at (cursor position + offset) to value.
void setCursorImagePosition(const ImageVector &position)
Sets the cursor to the given 6D position relative to the origin of the complete image region.
DATATYPE * getCursorPointerWithOffset(MLint dx, MLint dy, MLint dz) const
Returns the cursor pointer of the voxel computed from the current cursor shifted by (dx,...
void setCursorPosition(const DATATYPE *pointer)
Sets the cursor to the given pointer where pointer is the memory address of the voxel.
void moveCursorY()
Moves the cursor forward in y direction.
void moveCursorX()
Moves the cursor forward in x direction.
TSubImageWithCursor(const TSubImageWithCursor &subImage)
Constructor with TSubImageWithCursor.
TSubImageWithCursor(const SubImage &subImage)
Constructor with SubImage.
void moveCursorU()
Moves the cursor forward in u direction.
DATATYPE getCursorValueWithOffset(const ImageVector &offset) const
Returns the voxel value at (cursor position + offset)
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.
void setCursorSubImagePosition(const ImageVector &position)
Sets the cursor to the given position relative to the origin of the subimage region.
DATATYPE * getCursorPointer() const
TSubImageWithCursor()
Default constructor.
TSubImageWithCursor & operator=(const TSubImageWithCursor< DATATYPE > &tSubImg)
Assignment operator to get an identical copy.
void setCursorValueWithOffset(MLint dx, MLint dy, MLint dz, DATATYPE value)
Sets voxel value at (cursor position + (dx, dy,dz)) to value.
This template class manages/represents a rectangular 6D image region in memory that is organized line...
TSubImage(const SubImage &subImage)
Constructor to build a typed subimage from an untyped subImage.
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 ...
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 ...
void copySubImageTyped(const TSubImage< FROM_DATATYPE > &typedFromImg, const ScaleShiftData &scaleShiftData)
Copies image data from the subimage fromImg into the overlapping region of this subimage.
DATATYPE * getImagePointer(const ImageVector &position)
TSubImage(const TSubImage< DATATYPE > &typedSubImage)
Copy constructor to get an identical copy.
void copySubImageReorderColorPlanesToInterleaved(const TSubImage< FROM_DATATYPE > &typedFromImage, const ScaleShiftData &scaleShiftData)
Implements special case for void copySubImageTyped(const TSubImage<FROM_DATATYPE> &typedFromImg,...
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...
DATATYPE getImageValue(MLint x, MLint y) const
Returns the 2D voxel value from the given position (x, y).
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...
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...
void setImageValue(const ImageVector &position, DATATYPE value)
Sets the 6D voxel at the given position to the given value.
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...
ConstTSubImageCursor< DATATYPE > ConstCursor
A read-only cursor.
~TSubImage() override=default
Virtual destructor to suppress compiler warnings.
void fill(DATATYPE value)
Sets all voxel values in subimage to value.
ImageVector convertPointerToImagePosition(DATATYPE *pointer) const
Returns the 6D voxel coordinates corresponding to the memory address pointer.
DATATYPE & operator[](const ImageVector &position)
Reference access to voxel value at the given position.
DATATYPE getImageValue(MLint x, MLint y, MLint z) const
Returns the 3D voxel value from given position (x, y, z).
TSubImageCursor< DATATYPE > Cursor
A read/write cursor.
ImageVector convertPointerToSubImagePosition(DATATYPE *pointer) const
Returns the 6D voxel coordinates corresponding to the memory address pointer.
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...
TSubImage()
Default constructor to build a typed subimage (with an empty box) from scratch.
DATATYPE * getData()
DATATYPE getImageValue(const ImageVector &position) const
Returns the 6D voxel value from the given position.
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...
void fillInvalidRegionWithValue(DATATYPE value)
Fills the invalid region (everything outside of getValidRegion()) with the given value.
DATATYPE * getSubImagePointer(const ImageVector &position)
const DATATYPE & operator[](const ImageVector &position) const
Constant reference access to voxel value at the given position.
DATATYPE * getImagePointer(MLint x, MLint y, MLint z)
DATATYPE ComponentType
A typedef to 'export' the type of voxels components.
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.
void fillBordersWithValue(const SubImageBox &box, DATATYPE fillValue)
Fills all regions with fillValue that are not covered by box.
DATATYPE getSubImageValue(const ImageVector &position) const
Returns voxel value at the given position where position is relative to the origin of the subimage re...
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...
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...
void convertPointerToSubImagePosition(DATATYPE *pointer, MLint *x, MLint *y, MLint *z) const
Returns the 3D voxel coordinates corresponding to the memory address pointer.
TSubImage & operator=(const TSubImage< DATATYPE > &typedSubImage)
Assignment operator to get an identical copy.
void setImageValue(MLint x, MLint y, DATATYPE value)
Sets the 2D voxel at the given position (x, y) to the the given value.
const DATATYPE * getData() const
Returns the memory address of the image region. Overloads methods from SubImage.
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...
void convertPointerToImagePosition(DATATYPE *pointer, MLint *x, MLint *y, MLint *z) const
Returns the 3D voxel coordinates corresponding to the memory address pointer.
DATATYPE * getSubImagePointer(MLint x, MLint y, MLint z)
void fillInvalidRegionWithBorderValues()
Fills the invalid region (i.e., everything outside of getValidRegion() ) with the values on the borde...
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)
#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.
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.
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
TSubImage< T > & tsubimage_cast(SubImage &subImg)
STL namespace.
MLEXPORT std::ostream & operator<<(std::ostream &s, const ml::Field &v)
Overloads the operator '<<' for stream output of Field objects.
TypeTraits for scalar ML datatypes.