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 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 // Set box the data is correlated with.
172 setBox(subImage.getBox());
173
174 // Set correct data type enum.
175 setDataType(subImage.getDataType());
176
177 // Store data pointer (but NOT the memory block handle)
178 setData(subImage.getData());
179
180 // Set the source image extent
181 setSourceImageExtent(subImage.getSourceImageExtent());
182
183 // Check 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 // Get 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
587 //
588 //Note: The following function definition must be implemented in the class definition
589 // See BUG: LNK2001 on Member Function When Use Nested Class Template, Article ID: Q128789
590 template <typename FROM_DATATYPE>
591 void copySubImageTyped(const TSubImage<FROM_DATATYPE> &typedFromImg, const ScaleShiftData& scaleShiftData)
592 {
593 // Any box empty? Then no copy is necessary.
594 if (getBox().isEmpty() || typedFromImg.getBox().isEmpty()){
595 return;
596 }
597
598 if (scaleShiftData.getReorderMode() == ScaleShiftData::ReorderColorPlanesToInterleaved) {
599 copySubImageReorderColorPlanesToInterleaved(typedFromImg, scaleShiftData);
600 return;
601 }
602
603 // Get double and long double versions of scale and shift values.
604 const MLdouble scaleDbl = scaleShiftData.getScale();
605 const MLdouble shiftDbl = scaleShiftData.getShift();
606
607 // Check for identical scaling and use default copying then.
608 if (MLValuesAreEqual(scaleDbl, 1.0, 1.0) && MLValuesAreEqual(shiftDbl, 0.0, 1.0)){
609 copySubImage(typedFromImg);
610 return;
611 }
612
613 // Get data type properties. If we calculate with normal data types then we calculate in double values;
614 // on long double built-in types we use long double, and if we use extended types we remain in extended types.
615 const MLint isDTScalarType = MLIsScalarTypePtr(static_cast<DATATYPE*>(nullptr));
616 const MLint isFDTScalarType = MLIsScalarTypePtr(static_cast<FROM_DATATYPE*>(nullptr));
617
618 if (getDataType()==typedFromImg.getDataType()){
619 if (getBox()==typedFromImg.getBox()){
620 // Images have same data type and same position/extent:
621 //-----------------------------------------------------
622 const FROM_DATATYPE *fromPt = typedFromImg.getData();
623 DATATYPE *toPt = getData();
624
625 // Check data pointers and print errors if necessary.
627
628 // Get number and the size in bytes of all voxels of this subimage.
629 const MLint size = getNumVoxels();
630 const MLint bytesize = size * MLSizeOf(getDataType());
631
632 // Copy the memory to the target buffer, it must fit since types are identical.
633 memcpy( toPt, fromPt, bytesize );
634
635 // When we work with extended types we must avoid to change to double during calculations since
636 // that causes information loss. In normal case we remain in double.
637 if (!isDTScalarType){
638 // NOTE/TODO:
639 // Currently extended types must support adding and multiplying with doubles
640 // for this to work.
641 for (DATATYPE* toPtEnd=toPt+size; toPt<toPtEnd; ++toPt){
642 *toPt=static_cast<DATATYPE>(static_cast<DATATYPE>(*toPt)*scaleDbl + shiftDbl);
643 }
644 }
645 else{
646 for (DATATYPE* toPtEnd=toPt+size; toPt<toPtEnd; ++toPt){
647 *toPt=static_cast<DATATYPE>( static_cast<MLdouble>(*toPt)*scaleDbl + shiftDbl);
648 }
649 }
650 }
651 else{
652 // Images have same data type:
653 //----------------------------
654 // Calculate intersection of both subimages. Copy only if intersection is not empty.
655 const SubImageBox intersection = SubImageBox::intersect(typedFromImg.getBox(),getBox());
656 if (!intersection.isEmpty()){
657
658 // Check data pointers and print errors if necessary.
659 _ML_CHECK_SUBIMAGE_DATA_POINTERS(typedFromImg.getData(), getData());
660
661 ImageVector p;
662 const FROM_DATATYPE *fromPt = nullptr;
663 DATATYPE *toPt = nullptr,
664 *toPt_ = nullptr,
665 *toPtEnd = nullptr;
666 const ImageVector fromStr = typedFromImg.getStride();
667 const ImageVector toStr = getStride();
668 const MLint dist = intersection.v2.x - intersection.v1.x;
669 const MLint size_x = dist+1;
670 const MLint bytesize_x = size_x * MLSizeOf(getDataType());
671
672 // Traverse all 6 dimensions.
673 for (p.u=intersection.v1.u; p.u<=intersection.v2.u; ++p.u){
674 for (p.t=intersection.v1.t; p.t<=intersection.v2.t; ++p.t){
675 for (p.c=intersection.v1.c; p.c<=intersection.v2.c; ++p.c){
676 for (p.z=intersection.v1.z; p.z<=intersection.v2.z; ++p.z){
677
678 // Get start position to each slice of data.
679 const ImageVector pos(intersection.v1.x, intersection.v1.y, p.z, p.c, p.t, p.u);
680 fromPt = typedFromImg.getImagePointer(pos);
681 toPt = getImagePointer(pos);
682 ML_CHECK_THROW(fromPt);
683 ML_CHECK_THROW(toPt);
684
685 for (p.y=intersection.v1.y; p.y<=intersection.v2.y; ++p.y,fromPt+=fromStr.y,toPt+=toStr.y){
686
687 // Copy buffer to target buffer. Below we work only on one buffer for rescaling.
688 memcpy(toPt, fromPt, bytesize_x);
689 toPt_ = toPt;
690
691 if (!isDTScalarType){
692 // See description in upper case "if (getDataType()==typedFromImg.getDataType())".
693 for (toPtEnd = toPt_+size_x;
694 toPt_<toPtEnd;
695 ++toPt_){
696 *toPt_=static_cast<DATATYPE>(static_cast<DATATYPE>(*toPt_)*scaleDbl + shiftDbl);
697 }
698 }
699 else{
700 for (toPtEnd = toPt_+size_x;
701 toPt_<toPtEnd;
702 ++toPt_){
703 *toPt_=static_cast<DATATYPE>(static_cast<MLdouble>(*toPt_)*scaleDbl + shiftDbl);
704 }
705 }
706 }
707 }
708 }
709 }
710 }
711 } // if (!intersection.isEmpty())
712 } // else
713 } // if (getDataType()==typedFromImg.getDataType())
714
715 // Images have different data type:
716 //---------------------------------
717 else{
718 // Copy overlap of both subimages and copy only if it is not empty.
719 const SubImageBox intersection = SubImageBox::intersect(typedFromImg.getBox(),getBox());
720 if (!intersection.isEmpty()){
721
722 // Check data pointers and print errors if necessary.
723 _ML_CHECK_SUBIMAGE_DATA_POINTERS(typedFromImg.getData(), getData());
724
725 ImageVector p;
726 const FROM_DATATYPE *fromPt = nullptr;
727 DATATYPE *toPt = nullptr;
728
729 // Traverse all 6 dimensions.
730 for (p.u=intersection.v1.u; p.u<=intersection.v2.u; ++p.u){
731 for (p.t=intersection.v1.t; p.t<=intersection.v2.t; ++p.t){
732 for (p.c=intersection.v1.c; p.c<=intersection.v2.c; ++p.c){
733 for (p.z=intersection.v1.z; p.z<=intersection.v2.z; ++p.z){
734 for (p.y=intersection.v1.y; p.y<=intersection.v2.y; ++p.y){
735
736 // Get start position to each slice of data.
737 const ImageVector pos(intersection.v1.x,p.y,p.z,p.c,p.t,p.u);
738 fromPt = typedFromImg.getImagePointer(pos);
739 toPt = getImagePointer(pos);
740 const MLint startX = intersection.v1.x;
741 const MLint endX = intersection.v2.x;
742
743 if (!isFDTScalarType){
744 // When we work with extended types we must avoid to change to double during calculations since
745 // that causes information loss. In normal case we remain in double.
746 for (p.x = startX; p.x <= endX; ++p.x, ++fromPt, ++toPt){
747 *toPt=static_cast<DATATYPE>(static_cast<FROM_DATATYPE>(*fromPt)*scaleDbl + shiftDbl);
748 }
749 }
750 else{
751 for (p.x = startX; p.x <= endX; ++p.x, ++fromPt, ++toPt){
752 *toPt=static_cast<DATATYPE>(static_cast<MLdouble>(*fromPt)*scaleDbl + shiftDbl);
753 }
754 }
755 }
756 }
757 }
758 }
759 } // for (p.u)
760
761 } // if (!intersection.isEmpty())
762
763 } // else of if (getDataType()==typedFromImg.getDataType())
764 }
765
766
768
769
770 //-------------------------------------------------------------------------------------------
773 //-------------------------------------------------------------------------------------------
774
775 //---------------------------------------------------------------------------
777 //---------------------------------------------------------------------------
778 inline void fill(DATATYPE value)
779 {
780 ML_CHECK_THROW(_data);
781
782 const DATATYPE* dataEnd = static_cast<DATATYPE*>(_data) + getNumVoxels();
783
784 for (DATATYPE* i = static_cast<DATATYPE*>(_data); i<dataEnd; ++i){ *i=value; }
785 };
786
787
788 //-------------------------------------------------------------------------------------------
794 //-------------------------------------------------------------------------------------------
795 inline void fillBordersWithValue(const SubImageBox& box, DATATYPE fillValue)
796 {
797 SubImage::fillBordersWithTypeData(box, reinterpret_cast<const MLTypeData*>(&fillValue));
798 }
799
800 //-------------------------------------------------------------------------------------------
803 //-------------------------------------------------------------------------------------------
804 inline void fillInvalidRegionWithValue(DATATYPE value) {
805 fillBordersWithValue(getValidRegion(), value);
806 }
807
808 //-------------------------------------------------------------------------------------------
812 //-------------------------------------------------------------------------------------------
814 fillBordersWithBorderValues(getValidRegion());
815 }
816
818};
819
820//---------------------------------------------------------------------------
822//---------------------------------------------------------------------------
823template <typename DATATYPE>
825
826protected:
827
829 _data = const_cast<DATATYPE*>(subImage.getData());
830 _subImageOffset = subImage.getBox().v1;
831 _stride = subImage.getStride();
832 _cursor = _data;
833 }
834
835public:
836
837 //---------------------------------------------------------------------------
840 //---------------------------------------------------------------------------
843 inline void setSubImagePosition(const ImageVector& position) { _cursor = _data+ImageVector::dot(position,_stride); }
846 inline void setSubImagePosition(MLint x, MLint y, MLint z) { _cursor = _data+_stride.x*x+_stride.y*y+_stride.z*z; }
849 inline void setImagePosition(const ImageVector& position) { _cursor = _data + _ML_TSUBIMG_SUBDOT6(position,_subImageOffset,_stride); }
852 inline void setImagePosition(MLint x, MLint y, MLint z) { _cursor = _data+ + _ML_TSUBIMG_SUBDOT3(x,y,z,_subImageOffset,_stride); }
854 inline void setPosition(const DATATYPE *pointer) { _cursor = const_cast<DATATYPE*>(pointer); }
856 inline void moveByOffset(const ImageVector& offset) { _cursor += ImageVector::dot(offset,_stride); }
858 inline void moveByOffset(MLint x, MLint y, MLint z) { _cursor += _stride.x*x+_stride.y*y+_stride.z*z; }
860 inline void moveX() { _cursor += _stride.x; }
862 inline void moveY() { _cursor += _stride.y; }
864 inline void moveZ() { _cursor += _stride.z; }
866 inline void moveC() { _cursor += _stride.c; }
868 inline void moveT() { _cursor += _stride.t; }
870 inline void moveU() { _cursor += _stride.u; }
872 inline void reverseMoveX() { _cursor -= _stride.x; }
874 inline void reverseMoveY() { _cursor -= _stride.y; }
876 inline void reverseMoveZ() { _cursor -= _stride.z; }
878 inline void reverseMoveC() { _cursor -= _stride.c; }
880 inline void reverseMoveT() { _cursor -= _stride.t; }
882 inline void reverseMoveU() { _cursor -= _stride.u; }
883
885
886 //---------------------------------------------------------------------------
889 // Note: All these functions do not need explicit 64 bit arithmetic, because
890 // pointer arithmetic always goes from valid address area to another
891 // valid address area even on 32 systems and calculations do not fall
892 // outside valid ranges.
893 //---------------------------------------------------------------------------
895 inline DATATYPE getValue() const { return *(_cursor); }
896
898 inline DATATYPE getValueWithOffset(const ImageVector& offset) const { return *(_cursor+ImageVector::dot(offset,_stride)); }
899
901 inline DATATYPE getValueWithOffset(MLint dx, MLint dy, MLint dz) const { return *(_cursor+_stride.x*dx+_stride.y*dy+_stride.z*dz); }
902
904
905protected:
907 DATATYPE* _data;
913 DATATYPE* _cursor;
914};
915
916//---------------------------------------------------------------------------
919//---------------------------------------------------------------------------
920template <typename DATATYPE>
922
924
925public:
926 ConstTSubImageCursor(const TSubImage<DATATYPE>& subImage) : TSubImageCursorBase<DATATYPE>(subImage) {
927 }
928
929 //---------------------------------------------------------------------------
934 inline const DATATYPE* getPointer() const { return T::_cursor; }
936 inline const DATATYPE* getPointerWithOffset(const ImageVector& offset) const { return T::_cursor+ImageVector::dot(offset,T::_stride); }
938 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); }
940};
941
942//---------------------------------------------------------------------------
945//---------------------------------------------------------------------------
946template <typename DATATYPE>
947class TSubImageCursor : public TSubImageCursorBase<DATATYPE> {
948
950
951public:
952
953 TSubImageCursor(TSubImage<DATATYPE>& subImage) : TSubImageCursorBase<DATATYPE>(subImage) {
954 }
955
956 //---------------------------------------------------------------------------
961 inline DATATYPE* getPointer() const { return T::_cursor; }
963 inline DATATYPE* getPointerWithOffset(const ImageVector& offset) const { return T::_cursor+ImageVector::dot(offset,T::_stride); }
965 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); }
967
968 //---------------------------------------------------------------------------
971 // Note: All these functions do not need explicit 64 bit arithmetic, because
972 // pointer arithmetic always goes from valid address area to another
973 // valid address area even on 32 systems and calculations do not fall
974 // outside valid ranges.
975 //---------------------------------------------------------------------------
977 inline void setValue(DATATYPE value) const { *(T::_cursor) = value; }
979 inline void setValueWithOffset(const ImageVector& offset, DATATYPE value) const { *(T::_cursor+ImageVector::dot(offset,T::_stride))=value; }
981 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; }
983};
984
985//-------------------------------------------------------------------------
988//-------------------------------------------------------------------------
989template <typename DATATYPE>
990class TSubImageWithCursor : public TSubImage<DATATYPE>
991{
992 typedef TSubImage<DATATYPE> T;
993
994public:
996 TSubImageWithCursor():TSubImage<DATATYPE>(), _cursor(nullptr)
997 {
998 }
1000 TSubImageWithCursor(const TSubImage<DATATYPE>& subImage):TSubImage<DATATYPE>(subImage), _cursor(nullptr)
1001 {
1002 }
1003
1005 TSubImageWithCursor(const SubImage& subImage):TSubImage<DATATYPE>(subImage), _cursor(nullptr)
1006 {
1007 }
1008
1010 TSubImageWithCursor(const TSubImageWithCursor& subImage):TSubImage<DATATYPE>(subImage),_cursor(subImage._cursor)
1011 {
1012 }
1013
1017 {
1019 _cursor = tSubImg._cursor;
1020 return *this;
1021 }
1022
1023 //---------------------------------------------------------------------------
1026 //---------------------------------------------------------------------------
1029 inline void setCursorSubImagePosition(const ImageVector& position) { _cursor = static_cast<DATATYPE*>(T::_data)+ImageVector::dot(position,T::_stride); }
1032 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; }
1035 inline void setCursorImagePosition(const ImageVector& position) { _cursor = static_cast<DATATYPE*>(T::_data)+ _ML_TSUBIMG_SUBDOT6(position, T::_box.v1 ,T::_stride); }
1038 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); }
1040 inline void setCursorPosition(const DATATYPE* pointer) { _cursor = const_cast<DATATYPE*>(pointer); }
1042 inline void moveCursorByOffset(const ImageVector& offset) { _cursor += ImageVector::dot(offset,T::_stride); }
1044 inline void moveCursorByOffset(MLint x, MLint y, MLint z) { _cursor += T::_stride.x*x+T::_stride.y*y+T::_stride.z*z; }
1046 inline void moveCursorX() { _cursor += T::_stride.x; }
1048 inline void moveCursorY() { _cursor += T::_stride.y; }
1050 inline void moveCursorZ() { _cursor += T::_stride.z; }
1052 inline void moveCursorC() { _cursor += T::_stride.c; }
1054 inline void moveCursorT() { _cursor += T::_stride.t; }
1056 inline void moveCursorU() { _cursor += T::_stride.u; }
1058 inline void reverseMoveCursorX() { _cursor -= T::_stride.x; }
1060 inline void reverseMoveCursorY() { _cursor -= T::_stride.y; }
1062 inline void reverseMoveCursorZ() { _cursor -= T::_stride.z; }
1064 inline void reverseMoveCursorC() { _cursor -= T::_stride.c; }
1066 inline void reverseMoveCursorT() { _cursor -= T::_stride.t; }
1068 inline void reverseMoveCursorU() { _cursor -= T::_stride.u; }
1069
1071
1072 //---------------------------------------------------------------------------
1075 // Note: All these functions do not need explicit 64 bit arithmetic, because
1076 // pointer arithmetic always goes from valid address area to another
1077 // valid address area even on 32 systems and calculations do not fall
1078 // outside valid ranges.
1079 //---------------------------------------------------------------------------
1081 inline DATATYPE getCursorValue() const { return *(_cursor); }
1083 inline DATATYPE getCursorValueWithOffset(const ImageVector& offset) const { return *(_cursor+ImageVector::dot(offset,T::_stride)); }
1085 inline DATATYPE getCursorValueWithOffset(MLint dx, MLint dy, MLint dz) const { return *(_cursor+T::_stride.x*dx+T::_stride.y*dy+T::_stride.z*dz); }
1086
1088
1089 //---------------------------------------------------------------------------
1094 inline DATATYPE* getCursorPointer() const { return _cursor; }
1096 inline DATATYPE* getCursorPointerWithOffset(const ImageVector& offset) const { return _cursor+ImageVector::dot(offset,T::_stride); }
1098 inline DATATYPE* getCursorPointerWithOffset(MLint dx, MLint dy, MLint dz) const { return (_cursor+T::_stride.x*dx+T::_stride.y*dy+T::_stride.z*dz); }
1100
1101 //---------------------------------------------------------------------------
1104 // Note: All these functions do not need explicit 64 bit arithmetic, because
1105 // pointer arithmetic always goes from valid address area to another
1106 // valid address area even on 32 systems and calculations do not fall
1107 // outside valid ranges.
1108 //---------------------------------------------------------------------------
1110 inline void setCursorValue(DATATYPE value) { *(_cursor) = value; }
1112 inline void setCursorValueWithOffset(const ImageVector& offset, DATATYPE value) { *(_cursor+ImageVector::dot(offset,T::_stride))=value; }
1114 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; }
1115
1117
1118private:
1120 DATATYPE* _cursor;
1121};
1122
1123//---------------------------------------------------------------------------
1134//---------------------------------------------------------------------------
1135template <typename T>
1137{
1138 // Check whether template type and real data type match if there is valid data.
1139 if (subImg.getData() && !TypeTraits<T>::matches(subImg.getDataType()) )
1140 {
1141 ML_PRINT_FATAL_ERROR("tsubimage_cast", ML_BAD_DATA_TYPE,
1142 "Mismatch of data type between argument and template typename.");
1143 }
1144 return *(static_cast<TSubImage<T>* >(&subImg));
1145}
1146
1147template <typename T>
1149{
1150 // Check whether template type and real data type match if there is valid data.
1151 if (subImg.getData() && !TypeTraits<T>::matches(subImg.getDataType()) )
1152 {
1153 ML_PRINT_FATAL_ERROR("tsubimage_cast", ML_BAD_DATA_TYPE,
1154 "Mismatch of data type between argument and template typename.");
1155 }
1156 return *(static_cast<const TSubImage<T>* >(&subImg));
1157}
1158
1159template <typename T>
1161{
1162 // Check whether template type and real data type match if there is valid data.
1163 if (subImg->getData() && !TypeTraits<T>::matches(subImg->getDataType()) )
1164 {
1165 ML_PRINT_FATAL_ERROR("tsubimage_cast", ML_BAD_DATA_TYPE,
1166 "Mismatch of data type between argument and template typename.");
1167 }
1168 return static_cast<TSubImage<T>* >(subImg);
1169}
1170
1171template <typename T>
1173{
1174 // Check whether template type and real data type match if there is valid data.
1175 if (subImg->getData() && !TypeTraits<T>::matches(subImg->getDataType()) )
1176 {
1177 ML_PRINT_FATAL_ERROR("tsubimage_cast", ML_BAD_DATA_TYPE,
1178 "Mismatch of data type between argument and template typename.");
1179 }
1180 return static_cast<const TSubImage<T>* >(subImg);
1181}
1182
1184
1185
1186ML_END_NAMESPACE
1187
1188namespace std {
1189
1190 //---------------------------------------------------------------------------
1191 // Debug printing for TSubImage.
1192 //---------------------------------------------------------------------------
1193
1196 template <typename DATATYPE>
1197 inline ostream &operator<<(ostream &ostr, const ML_NAMESPACE::TSubImage<DATATYPE> &v)
1198 {
1199 // Get box of subimage and traverse all of its voxels.
1200 const ML_NAMESPACE::SubImageBox& box = v.getBox();
1201 ML_NAMESPACE::ImageVector p;
1202 for (p.u=box.v1.u; p.u<=box.v2.u; ++p.u){
1203 for (p.t=box.v1.t; p.t<=box.v2.t; ++p.t){
1204 for (p.c=box.v1.c; p.c<=box.v2.c; ++p.c){
1205 for (p.z=box.v1.z; p.z<=box.v2.z; ++p.z){
1206 for (p.y=box.v1.y; p.y<=box.v2.y; ++p.y){
1207 // Print row of voxels after a single row start position.
1208 p.x = box.v1.x;
1209 ostr << p << ": ";
1210 for (; p.x<=box.v2.x; p.x++){
1211 ostr << v.getImageValue(p) << " ";
1212 }
1213 ostr << std::endl;
1214 }
1215 }
1216 }
1217 }
1218 }
1219 return ostr;
1220 }
1221
1222}
1223
1224#ifdef _MSC_VER
1225#pragma warning(pop)
1226#endif
1227
1228
1229#endif //of __mlTSubImage_H
1230
1231
1232
Predeclaration for const cursor.
ConstTSubImageCursor(const TSubImage< DATATYPE > &subImage)
const DATATYPE * getPointerWithOffset(const ImageVector &offset) const
Returns cursor position of voxel given from current cursor shifted by offset.
const DATATYPE * getPointerWithOffset(MLint dx, MLint dy, MLint dz) const
Returns cursor position of voxel given from current cursor shifted by (dx, dy, dz).
const DATATYPE * getPointer() const
This class manages/represents a rectangular 6d image region which 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
Return 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 scale constant from transformation y=scale*x+offset.
ReorderMode getReorderMode() const
Get the reorder mode.
DT getShift() const
Returns addition constant shift from 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 cursor backward in c direction.
void moveT()
Moves cursor forward in t direction.
void reverseMoveX()
Moves cursor backward in x direction.
void moveZ()
Moves cursor forward in z direction.
void setPosition(const DATATYPE *pointer)
Sets cursor to the given pointer where the pointer is the memory address of the voxel.
void reverseMoveY()
Moves cursor backward in y direction.
DATATYPE getValue() const
Returns voxel value at cursor position.
void reverseMoveT()
Moves cursor backward in t direction.
ImageVector _stride
Stride for the sub image.
void moveU()
Moves cursor forward in u direction.
void setSubImagePosition(MLint x, MLint y, MLint z)
Sets 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 voxel value at (cursor position + (dx, dy, dz))
void moveX()
Moves cursor forward in x direction.
DATATYPE getValueWithOffset(const ImageVector &offset) const
Returns voxel value at (cursor position + offset).
ImageVector _subImageOffset
SubImage offset in original image.
DATATYPE * _data
SubImage data.
void reverseMoveZ()
Moves cursor backward in z direction.
void setImagePosition(const ImageVector &position)
Sets cursor to the given 6d position relative to the origin of the complete image region.
void moveByOffset(const ImageVector &offset)
Moves cursor to cursor position + offset.
DATATYPE * _cursor
Cursor address for image data access.
void reverseMoveU()
Moves cursor backward in u direction.
TSubImageCursorBase(const TSubImage< DATATYPE > &subImage)
void moveY()
Moves cursor forward in y direction.
void setSubImagePosition(const ImageVector &position)
Sets cursor to the given position relative to the origin of the subimage region.
void moveByOffset(MLint x, MLint y, MLint z)
Moves cursor to cursor position + (x, y, z).
void setImagePosition(MLint x, MLint y, MLint z)
Sets cursor to the given 3d position (x, y, z) relative to the origin of the complete image region.
void moveC()
Moves cursor forward in c direction.
Predeclaration for cursor.
DATATYPE * getPointerWithOffset(const ImageVector &offset) const
Returns cursor position of voxel given from current cursor shifted by offset.
DATATYPE * getPointer() const
void setValueWithOffset(MLint dx, MLint dy, MLint dz, DATATYPE value) const
Sets voxel value at (cursor position + (dx, dy, dz)) to value.
TSubImageCursor(TSubImage< DATATYPE > &subImage)
void setValueWithOffset(const ImageVector &offset, DATATYPE value) const
Sets voxel value at (cursor position + offset) to value.
void setValue(DATATYPE value) const
Sets voxel value at cursor position to value.
DATATYPE * getPointerWithOffset(MLint dx, MLint dy, MLint dz) const
Returns cursor position of voxel given from current cursor shifted by (dx, dy, dz).
A class that offers a TSubImage with a TSubImageCursor.
void setCursorValue(DATATYPE value)
Sets the voxel value at cursor position to value.
void reverseMoveCursorC()
Moves cursor backward in c direction.
void moveCursorT()
Moves cursor forward in t direction.
void moveCursorByOffset(const ImageVector &offset)
Moves cursor to cursor position + offset.
void setCursorImagePosition(MLint x, MLint y, MLint z)
Sets cursor to the given 3d position (x, y, z) relative to the origin of the complete image region.
DATATYPE getCursorValue() const
Returns the voxel value at the cursor position.
void reverseMoveCursorU()
Moves cursor backward in u direction.
void reverseMoveCursorY()
Moves cursor backward in y direction.
DATATYPE getCursorValueWithOffset(MLint dx, MLint dy, MLint dz) const
Returns voxel value at (cursor position + (dx, dy, dz))
void reverseMoveCursorX()
Moves cursor backward in x direction.
void moveCursorByOffset(MLint x, MLint y, MLint z)
Moves cursor to cursor position + (x, y, z).
TSubImageWithCursor(const TSubImage< DATATYPE > &subImage)
Constructor with TSubImage.
void moveCursorZ()
Moves cursor forward in z direction.
void reverseMoveCursorZ()
Moves cursor backward in z direction.
void moveCursorC()
Moves cursor forward in c direction.
DATATYPE * getCursorPointerWithOffset(const ImageVector &offset) const
Returns cursor pointer of voxel given from current cursor shifted by offset.
void reverseMoveCursorT()
Moves 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 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 cursor pointer of voxel given from current cursor shifted by (dx, dy, dz).
void setCursorPosition(const DATATYPE *pointer)
Sets cursor to the given pointer where pointer is the memory address of the voxel.
void moveCursorY()
Moves cursor forward in y direction.
void moveCursorX()
Moves cursor forward in x direction.
TSubImageWithCursor(const TSubImageWithCursor &subImage)
Constructor with TSubImageWithCursor.
TSubImageWithCursor(const SubImage &subImage)
Constructor with SubImage.
void moveCursorU()
Moves 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 cursor to the given 3d position (x, y, z) relative to the origin of the subimage region.
void setCursorSubImagePosition(const ImageVector &position)
Sets 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 which is organized lin...
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 begin of the c...
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 DATATY...
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 begin of th...
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 shut up compiler warnings.
void fill(DATATYPE value)
Sets all voxel values in subimage to value.
ImageVector convertPointerToImagePosition(DATATYPE *pointer) const
Returns 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 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 begin of the subima...
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 begin of th...
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 which 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 minimum and maximum values of the region which is part of subimage box ...
void convertPointerToSubImagePosition(DATATYPE *pointer, MLint *x, MLint *y, MLint *z) const
Returns 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 memory address of image region (Overloads method 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 positionis relative...
void convertPointerToImagePosition(DATATYPE *pointer, MLint *x, MLint *y, MLint *z) const
Returns 3d voxel coordinates corresponding to the memory address pointer.
DATATYPE * getSubImagePointer(MLint x, MLint y, MLint z)
void fillInvalidRegionWithBorderValues()
Fills the invalid region (everything outside of getValidRegion()) with the values on the borders of t...
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 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; t...
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.