MeVisLabToolboxReference
|
00001 // **InsertLicense** code 00002 //------------------------------------------------------------------------- 00011 //------------------------------------------------------------------------- 00012 #ifndef __mlTSubImage_H 00013 #define __mlTSubImage_H 00014 00015 // ML-includes 00016 #ifndef __mlInitSystemML_H 00017 #include "mlInitSystemML.h" 00018 #endif 00019 #ifndef __mlSubImage_H 00020 #include "mlSubImage.h" 00021 #endif 00022 #ifndef __mlTypeTraits_H 00023 #include "mlTypeTraits.h" 00024 #endif 00025 00026 #include "mlTemplateSupport.h" 00027 00028 #ifdef _MSC_VER 00029 #pragma warning(push) 00030 // warning C4244: 'Argument': Konvertierung von 'typ1' in 'typ2', möglicher Datenverlust 00031 #pragma warning(disable: 4244) 00032 // warning C4127: Bedingter Ausdruck ist konstant 00033 #pragma warning(disable: 4127) 00034 #endif 00035 00036 ML_START_NAMESPACE 00037 00038 00039 00040 00042 template <typename DATATYPE> class TSubImageCursor; 00044 template <typename DATATYPE> class ConstTSubImageCursor; 00045 00046 #ifdef ML_IS_64_BIT_SYSTEM 00047 00049 #define _ML_TSUBIMG_SUBDOT6(pos, offset, stride) \ 00050 (((pos).x - (offset).x) * (stride).x + \ 00051 ((pos).y - (offset).y) * (stride).y + \ 00052 ((pos).z - (offset).z) * (stride).z + \ 00053 ((pos).c - (offset).c) * (stride).c + \ 00054 ((pos).t - (offset).t) * (stride).t + \ 00055 ((pos).u - (offset).u) * (stride).u) 00056 00058 #define _ML_TSUBIMG_SUBDOT3(x, y, z, offset, stride) \ 00059 (((x) - (offset).x) * (stride).x + \ 00060 ((y) - (offset).y) * (stride).y + \ 00061 ((z) - (offset).z) * (stride).z) 00062 00064 #define _ML_TSUBIMG_SUBDOT2(x, y, offset, stride) \ 00065 (((x) - (offset).x) * (stride).x + \ 00066 ((y) - (offset).y) * (stride).y) 00067 00068 #else 00069 00072 #define _ML_TSUBIMG_SUBDOT6(pos, offset, stride) \ 00073 (static_cast<MLint32>((pos).x - (offset).x) * static_cast<MLint32>((stride).x) + \ 00074 static_cast<MLint32>((pos).y - (offset).y) * static_cast<MLint32>((stride).y) + \ 00075 static_cast<MLint32>((pos).z - (offset).z) * static_cast<MLint32>((stride).z) + \ 00076 static_cast<MLint32>((pos).c - (offset).c) * static_cast<MLint32>((stride).c) + \ 00077 static_cast<MLint32>((pos).t - (offset).t) * static_cast<MLint32>((stride).t) + \ 00078 static_cast<MLint32>((pos).u - (offset).u) * static_cast<MLint32>((stride).u)) 00079 00082 #define _ML_TSUBIMG_SUBDOT3(x, y, z, offset, stride) \ 00083 (static_cast<MLint32>((x) - (offset).x) * static_cast<MLint32>((stride).x) + \ 00084 static_cast<MLint32>((y) - (offset).y) * static_cast<MLint32>((stride).y) + \ 00085 static_cast<MLint32>((z) - (offset).z) * static_cast<MLint32>((stride).z)) 00086 00089 #define _ML_TSUBIMG_SUBDOT2(x, y, offset, stride) \ 00090 (static_cast<MLint32>((x) - (offset).x) * static_cast<MLint32>((stride).x) + \ 00091 static_cast<MLint32>((y) - (offset).y) * static_cast<MLint32>((stride).y)) 00092 00093 #endif 00094 00095 //------------------------------------------------------------------------- 00138 //------------------------------------------------------------------------- 00139 template <typename DATATYPE> 00140 class TSubImage : public SubImage 00141 { 00142 00143 public: 00144 00146 typedef TSubImageCursor<DATATYPE> Cursor; 00148 typedef ConstTSubImageCursor<DATATYPE> ConstCursor; 00149 00150 //--------------------------------------------------------------------------- 00152 00153 //--------------------------------------------------------------------------- 00165 TSubImage(const SubImageBox& box, MLDataType dataType, void* data):SubImage(box, dataType, data) 00166 { 00167 ML_TRACE_IN( "TSubImage( )" ); 00168 ML_TRY 00169 { 00170 // Check whether template type and real data type match if there is valid data. 00171 if (data && !TypeTraits<DATATYPE>::matches(dataType) ) 00172 { 00173 ML_PRINT_FATAL_ERROR("TSubImage::TSubImage()", ML_BAD_DATA_TYPE, 00174 "Mismatch of data type between argument and template typename."); 00175 } 00176 } 00177 ML_CATCH_RETHROW; 00178 } 00179 00185 TSubImage() 00186 { 00187 ML_TRACE_IN( "TSubImage()" ); 00188 ML_TRY 00189 { 00190 // Set correct data type enum from template datatype. 00191 setDataType(TypeTraits<DATATYPE>::dataType); 00192 if (TypeTraits<DATATYPE>::dataType == ML_INVALID_DATA_TYPE) { 00193 ML_PRINT_FATAL_ERROR("TSubImage::TSubImage()", ML_BAD_DATA_TYPE, 00194 "Data type has no registered TypeTraits."); 00195 } 00196 } 00197 ML_CATCH_RETHROW; 00198 } 00199 00200 00207 TSubImage(const SubImage &subImage) 00208 { 00209 ML_TRACE_IN( "TSubImage( )" ); 00210 ML_TRY 00211 { 00212 // Set box the data is correlated with. 00213 setBox(subImage.getBox()); 00214 00215 // Set correct data type enum. 00216 setDataType(subImage.getDataType()); 00217 00218 // Store data pointer (but NOT the memory block handle) 00219 setData(subImage.getData()); 00220 00221 // Set the source image extent 00222 setSourceImageExtent(subImage.getSourceImageExtent()); 00223 00224 // Check whether template type and real data type match if there is valid data. 00225 // This check only works if TypeTraits has been specified for the argument type. 00226 if (subImage.getData() && !TypeTraits<DATATYPE>::matches(subImage.getDataType()) ) 00227 { 00228 ML_PRINT_FATAL_ERROR("TSubImage::TSubImage()", ML_BAD_DATA_TYPE, 00229 "Mismatch of data type between argument and template typename."); 00230 } 00231 } 00232 ML_CATCH_RETHROW; 00233 } 00234 00237 inline TSubImage(const TSubImage<DATATYPE>& typedSubImage) : 00238 SubImage (typedSubImage) 00239 { 00240 ML_TRACE_IN_TIME_CRITICAL( "TSubImage( )" ); 00241 } 00242 00244 inline virtual ~TSubImage(){ ML_TRACE_IN_TIME_CRITICAL("TSubImage::~TSubImage()"); } 00245 00248 inline TSubImage &operator=(const TSubImage<DATATYPE>& typedSubImage) 00249 { 00250 ML_TRACE_IN_TIME_CRITICAL( "TSubImage::operator=( )" ); 00251 ML_TRY 00252 { 00253 SubImage::operator=(typedSubImage); 00254 return *this; 00255 } 00256 ML_CATCH_RETHROW; 00257 } 00259 00260 //--------------------------------------------------------------------------- 00262 00263 //--------------------------------------------------------------------------- 00264 00266 inline const DATATYPE* getData() const { return static_cast<DATATYPE*>(_data); } 00267 inline DATATYPE* getData() { return static_cast<DATATYPE*>(_data); } 00268 00270 00271 //--------------------------------------------------------------------------- 00273 00274 //--------------------------------------------------------------------------- 00278 // 64 bit arithmetic is not needed here, because the pointer offset goes from the valid 00279 // address space to another position inside the valid address space. We do not 00280 // fall outside 32 bit ranges. 00282 inline const DATATYPE* getSubImagePointer(const ImageVector& position) const { return static_cast<DATATYPE*>(_data) + ImageVector::dot(position,_stride); } 00283 inline DATATYPE* getSubImagePointer(const ImageVector& position) { return static_cast<DATATYPE*>(_data) + ImageVector::dot(position,_stride); } 00285 00290 // 64 bit arithmetic is not needed here, because the pointer offset goes from the valid 00291 // address space to another position inside the valid address space. We do not 00292 // fall outside 32 bit ranges. 00294 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); } 00295 inline DATATYPE* getSubImagePointer(MLint x, MLint y, MLint z) { return static_cast<DATATYPE*>(_data) + (x*_stride.x + y*_stride.y + _stride.z*z); } 00297 00301 00302 inline const DATATYPE* getImagePointer(const ImageVector& position) const { return static_cast<DATATYPE*>(_data) + _ML_TSUBIMG_SUBDOT6(position, _box.v1, _stride); } 00303 inline DATATYPE* getImagePointer(const ImageVector& position) { return static_cast<DATATYPE*>(_data) + _ML_TSUBIMG_SUBDOT6(position, _box.v1, _stride); } 00305 00309 00310 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); } 00311 inline DATATYPE* getImagePointer(MLint x, MLint y, MLint z) { return static_cast<DATATYPE*>(_data) + _ML_TSUBIMG_SUBDOT3(x,y,z, _box.v1, _stride); } 00313 00314 00315 00316 //------------------------------------------------------------------------------------- 00318 00319 //------------------------------------------------------------------------------------- 00323 inline ImageVector convertPointerToSubImagePosition(DATATYPE* pointer) const 00324 { return getStride().getVectorPosition(pointer - static_cast<DATATYPE*>(_data)); } 00325 00331 inline void convertPointerToSubImagePosition(DATATYPE* pointer, MLint* x, MLint* y, MLint* z) const 00332 { 00333 ML_TRACE_IN( "TSubImage::convertPointerToSubImagePosition( )" ); 00334 ML_TRY 00335 { 00336 const MLint offset = pointer - static_cast<DATATYPE*>(_data); 00337 const ImageVector stride=getStride(); 00338 const ImageVector imgExt=getImageExtent(); 00339 00340 if (x){ 00341 ML_CHECK_THROW(stride.x); 00342 ML_CHECK_THROW(imgExt.x); 00343 *x = (offset/stride.x) % imgExt.x; 00344 } 00345 00346 if (y){ 00347 ML_CHECK_THROW(imgExt.y); 00348 ML_CHECK_THROW(stride.y); 00349 *y = (offset/stride.y) % imgExt.y; 00350 } 00351 00352 if (z){ 00353 ML_CHECK_THROW(imgExt.z); 00354 ML_CHECK_THROW(stride.z); 00355 *z = (offset/stride.z) % imgExt.z; 00356 } 00357 } 00358 ML_CATCH_RETHROW; 00359 } 00360 00361 00365 inline ImageVector convertPointerToImagePosition(DATATYPE* pointer) const 00366 { return convertPointerToSubImagePosition(pointer) + _box.v1; } 00367 00368 00374 inline void convertPointerToImagePosition(DATATYPE* pointer, MLint* x, MLint* y, MLint* z) const 00375 { 00376 convertPointerToSubImagePosition(pointer, x, y, z); 00377 if (x){ *x += _box.v1.x; } 00378 if (y){ *y += _box.v1.y; } 00379 if (z){ *z += _box.v1.z; } 00380 } 00382 00383 00384 00385 //--------------------------------------------------------------------------- 00387 00388 //--------------------------------------------------------------------------- 00389 00394 inline const DATATYPE& operator[](const ImageVector& position) const { return getImagePointer(position)[0]; } 00395 00400 inline DATATYPE& operator[](const ImageVector& position) { return getImagePointer(position)[0]; } 00401 00405 inline void setSubImageValue(const ImageVector& position, DATATYPE value) { static_cast<DATATYPE*>(_data)[ ImageVector::dot(position,_stride) ]=value; } 00406 00410 inline DATATYPE getSubImageValue(const ImageVector& position) const { return static_cast<DATATYPE*>(_data)[ ImageVector::dot(position,_stride) ]; } 00411 00415 inline void setSubImageValue(MLint x, MLint y, DATATYPE value) { static_cast<DATATYPE*>(_data)[ x*_stride.x + y*_stride.y ]=value; } 00419 inline DATATYPE getSubImageValue(MLint x, MLint y) const { return static_cast<DATATYPE*>(_data)[ x*_stride.x + y*_stride.y ]; } 00420 00424 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; } 00428 inline DATATYPE getSubImageValue(MLint x, MLint y, MLint z) const { return static_cast<DATATYPE*>(_data)[ x*_stride.x + y*_stride.y+_stride.z*z ]; } 00429 00433 inline void setImageValue(const ImageVector& position, DATATYPE value) { getImagePointer(position)[0] = value; } 00437 inline DATATYPE getImageValue(const ImageVector& position) const { return getImagePointer(position)[0]; } 00438 00442 inline void setImageValue(MLint x, MLint y, DATATYPE value) { static_cast<DATATYPE*>(_data)[_ML_TSUBIMG_SUBDOT2(x,y,_box.v1, _stride)]=value; } 00446 inline DATATYPE getImageValue(MLint x, MLint y) const { return static_cast<DATATYPE*>(_data)[_ML_TSUBIMG_SUBDOT2(x,y,_box.v1, _stride)]; } 00447 00451 inline void setImageValue(MLint x, MLint y, MLint z, DATATYPE value){ getImagePointer(x,y,z)[0] = value; } 00455 inline DATATYPE getImageValue(MLint x, MLint y, MLint z) const { return getImagePointer(x,y,z)[0]; } 00456 00458 00459 00460 //--------------------------------------------------------------------------- 00462 00463 //--------------------------------------------------------------------------- 00474 MLint calculateMinMax(DATATYPE& minValue, DATATYPE& maxValue, const SubImageBox * const validBox=NULL) const 00475 { 00476 ML_TRACE_IN( "TSubImage::calculateMinMax( )" ); 00477 ML_TRY 00478 { 00479 // If passed box pointer is valid then compute intersection with 00480 // this subimage box, otherwise use non intersected subimage box of this. 00481 const SubImageBox& thisBox = getBox(); 00482 const SubImageBox box = validBox ? SubImageBox::intersect(thisBox, *validBox) : thisBox; 00483 00484 // Get number of voxels in subimage. Return 0/0 if subimage is empty. 00485 const MLint numVoxels = box.getNumVoxels(); 00486 if (numVoxels==0){ minValue=0; maxValue=0; return 0; } 00487 00488 // Set min/max to first voxel value. 00489 minValue = maxValue = getImageValue(box.v1); 00490 00491 // Simply scan all voxels if box is subimage box, it is faster. 00492 if (box == thisBox){ 00493 // Not empty. Get pointer to voxel directly after last voxel. 00494 00495 ML_CHECK_THROW(_data); 00496 const DATATYPE* dataEnd = static_cast<DATATYPE*>(_data) + numVoxels; 00497 00498 // Scan all voxels starting with the second one. 00499 for (DATATYPE* i=static_cast<DATATYPE*>(_data)+1; i<dataEnd; ++i) 00500 { 00501 if (*i < minValue){ minValue = *i; } 00502 if (*i > maxValue){ maxValue = *i; } 00503 } 00504 } 00505 else{ 00506 // Loop over all rows of the valid subimage region. 00507 ImageVector p; 00508 for (MLint u=box.v1.u; u <= box.v2.u; ++u){ 00509 for (MLint t=box.v1.t; t <= box.v2.t; ++t){ 00510 for (MLint c=box.v1.c; c <= box.v2.c; ++c){ 00511 for (MLint z=box.v1.z; z <= box.v2.z; ++z){ 00512 for (MLint y=box.v1.y; y <= box.v2.y; ++y){ 00513 // For inner loop move pointer. 00514 p.set(box.v1.x, y, z, c, t, u); 00515 const DATATYPE *dPtr = getImagePointer(p); 00516 const MLint pEnd = box.v2.x; 00517 for (MLint x=box.v1.x; x <= pEnd; ++x, ++dPtr){ 00518 if (*dPtr < minValue){ minValue = *dPtr; } 00519 if (*dPtr > maxValue){ maxValue = *dPtr; } 00520 } 00521 } 00522 } 00523 } 00524 } 00525 } 00526 } 00527 00528 // Return how many voxel have been scanned. 00529 return numVoxels; 00530 } 00531 ML_CATCH_RETHROW; 00532 }; 00534 00535 //--------------------------------------------------------------------------- 00537 00538 //--------------------------------------------------------------------------- 00539 00541 #define _ML_CHECK_SUBIMAGE_DATA_POINTERS(FROM_PTR, TO_PTR) \ 00542 /* Check for valid data pointers to avoid memory access errors. */ \ 00543 { \ 00544 if (!FROM_PTR || !TO_PTR){ \ 00545 ML_PRINT_ERROR("TSubImage::copySubImageTyped( )", \ 00546 ML_BAD_POINTER_OR_0, \ 00547 "Valid data pointers in source and target subimage required for" \ 00548 "subimage copying, thus call is ignored."); \ 00549 return; \ 00550 } \ 00551 } 00552 00556 template <typename FROM_DATATYPE> 00557 void copySubImageReorderColorPlanesToInterleaved(const TSubImage<FROM_DATATYPE>& typedFromImage, const ScaleShiftData& scaleShiftData) 00558 { 00559 ML_TRACE_IN( "TSubImage::copySubImageReorderColorPlanesToInterleaved( )" ); 00560 ML_TRY 00561 { 00562 // Copy in local variables to reduce calculations in getBox(). 00563 const SubImageBox& box =getBox(); 00564 const SubImageBox& tBox=typedFromImage.getBox(); 00565 00566 if (box.isEmpty() || tBox.isEmpty()){ return; } 00567 00568 // Calculate overlap of both subimages and copy only if overlap is not empty. 00569 const SubImageBox intersection = SubImageBox::intersect(typedFromImage.getBox(),getBox()); 00570 if (!intersection.isEmpty()){ 00571 00572 // Check data pointers and print errors if necessary. 00573 _ML_CHECK_SUBIMAGE_DATA_POINTERS(typedFromImage.getData(), getData()); 00574 00575 ImageVector p; 00576 const FROM_DATATYPE* fromPt = NULL; 00577 DATATYPE* toPt = NULL; 00578 00579 const ImageVector toExtent = getExtent(); 00580 const ImageVector toStrides = ImageVector(toExtent.c, toExtent.x, toExtent.y, toExtent.z, toExtent.t, toExtent.u).getStrides(); 00581 const ImageVector offsetReordered(_box.v1.c, _box.v1.x, _box.v1.y, _box.v1.z, _box.v1.t, _box.v1.u); 00582 00583 const MLdouble scaleDbl = static_cast<MLdouble>(scaleShiftData.getScale()); 00584 const MLdouble shiftDbl = static_cast<MLdouble>(scaleShiftData.getShift()); 00585 00586 // Check for identical scaling. 00587 const bool identicalScaling = MLValuesAreEqual(scaleDbl, static_cast<MLdouble>(1), static_cast<MLdouble>(1)) && 00588 MLValuesAreEqual(shiftDbl, static_cast<MLdouble>(0), static_cast<MLdouble>(1)); 00589 00590 // Traverse all voxels. 00591 if (identicalScaling) { 00592 for (p.u=intersection.v1.u; p.u<=intersection.v2.u; ++p.u) { 00593 for (p.t=intersection.v1.t; p.t<=intersection.v2.t; ++p.t) { 00594 for (p.c=intersection.v1.c; p.c<=intersection.v2.c; ++p.c) { 00595 for (p.z=intersection.v1.z; p.z<=intersection.v2.z; ++p.z) { 00596 for (p.y=intersection.v1.y; p.y<=intersection.v2.y; ++p.y) { 00597 00598 const ImageVector pos(intersection.v1.x,p.y,p.z,p.c,p.t,p.u); 00599 const ImageVector posReordered(p.c, intersection.v1.x,p.y,p.z,p.t,p.u); 00600 fromPt= typedFromImage.getImagePointer(pos); 00601 toPt = static_cast<DATATYPE*>(_data) + _ML_TSUBIMG_SUBDOT6(posReordered, offsetReordered, toStrides); 00602 00603 for (p.x = intersection.v1.x; p.x <= intersection.v2.x; ++p.x, ++fromPt) { 00604 *toPt = static_cast<DATATYPE>(*fromPt); 00605 toPt += toStrides.y; 00606 } 00607 } 00608 } 00609 } 00610 } 00611 } 00612 } else { 00613 for (p.u=intersection.v1.u; p.u<=intersection.v2.u; ++p.u) { 00614 for (p.t=intersection.v1.t; p.t<=intersection.v2.t; ++p.t) { 00615 for (p.c=intersection.v1.c; p.c<=intersection.v2.c; ++p.c) { 00616 for (p.z=intersection.v1.z; p.z<=intersection.v2.z; ++p.z) { 00617 for (p.y=intersection.v1.y; p.y<=intersection.v2.y; ++p.y) { 00618 00619 const ImageVector pos(intersection.v1.x,p.y,p.z,p.c,p.t,p.u); 00620 const ImageVector posReordered(p.c, intersection.v1.x,p.y,p.z,p.t,p.u); 00621 fromPt= typedFromImage.getImagePointer(pos); 00622 toPt = static_cast<DATATYPE*>(_data) + _ML_TSUBIMG_SUBDOT6(posReordered, offsetReordered, toStrides); 00623 00624 for (p.x = intersection.v1.x; p.x <= intersection.v2.x; ++p.x, ++fromPt) { 00625 *toPt = static_cast<DATATYPE>(static_cast<MLdouble>(*fromPt)*scaleDbl + shiftDbl); 00626 toPt += toStrides.y; 00627 } 00628 } 00629 } 00630 } 00631 } 00632 } 00633 } 00634 } // if (!intersection.isEmpty()) 00635 } // ML_TRY 00636 ML_CATCH_RETHROW; 00637 } 00638 00651 // 00652 //Note: The following function definition must be implemented in the class definition 00653 // See BUG: LNK2001 on Member Function When Use Nested Class Template, Article ID: Q128789 00654 template <typename FROM_DATATYPE> 00655 void copySubImageTyped(const TSubImage<FROM_DATATYPE> &typedFromImg, const ScaleShiftData& scaleShiftData) 00656 { 00657 ML_TRACE_IN( "TSubImage::copySubImageTyped( )" ); 00658 ML_TRY 00659 { 00660 // Any box empty? Then no copy is necessary. 00661 if (getBox().isEmpty() || typedFromImg.getBox().isEmpty()){ 00662 return; 00663 } 00664 00665 if (scaleShiftData.getReorderMode() == ScaleShiftData::ReorderColorPlanesToInterleaved) { 00666 copySubImageReorderColorPlanesToInterleaved(typedFromImg, scaleShiftData); 00667 return; 00668 } 00669 00670 // Get double and long double versions of scale and shift values. 00671 const MLdouble scaleDbl = scaleShiftData.getScale(); 00672 const MLdouble shiftDbl = scaleShiftData.getShift(); 00673 00674 // Check for identical scaling and use default copying then. 00675 if (MLValuesAreEqual(scaleDbl, 1.0, 1.0) && MLValuesAreEqual(shiftDbl, 0.0, 1.0)){ 00676 copySubImage(typedFromImg); 00677 return; 00678 } 00679 00680 // Get data type properties. If we calculate with normal data types then we calculate in double values; 00681 // on long double built-in types we use long double, and if we use extended types we remain in extended types. 00682 const MLint isDTScalarType = MLIsScalarTypePtr(static_cast<DATATYPE*>(NULL)); 00683 const MLint isFDTScalarType = MLIsScalarTypePtr(static_cast<FROM_DATATYPE*>(NULL)); 00684 00685 if (getDataType()==typedFromImg.getDataType()){ 00686 if (getBox()==typedFromImg.getBox()){ 00687 // Images have same data type and same position/extent: 00688 //----------------------------------------------------- 00689 const FROM_DATATYPE *fromPt = typedFromImg.getData(); 00690 DATATYPE *toPt = getData(); 00691 00692 // Check data pointers and print errors if necessary. 00693 _ML_CHECK_SUBIMAGE_DATA_POINTERS(fromPt, toPt); 00694 00695 // Get number and the size in bytes of all voxels of this subimage. 00696 const MLint size = getNumVoxels(); 00697 const MLint bytesize = size * MLSizeOf(getDataType()); 00698 00699 // Copy the memory to the target buffer, it must fit since types are identical. 00700 memcpy( toPt, fromPt, bytesize ); 00701 00702 // When we work with extended types we must avoid to change to double during calculations since 00703 // that causes information loss. In normal case we remain in double. 00704 if (!isDTScalarType){ 00705 // NOTE/TODO: 00706 // Currently extended types must support adding and multiplying with doubles 00707 // for this to work. 00708 for (DATATYPE* toPtEnd=toPt+size; toPt<toPtEnd; ++toPt){ 00709 *toPt=static_cast<DATATYPE>(static_cast<DATATYPE>(*toPt)*scaleDbl + shiftDbl); 00710 } 00711 } 00712 else{ 00713 for (DATATYPE* toPtEnd=toPt+size; toPt<toPtEnd; ++toPt){ 00714 *toPt=static_cast<DATATYPE>( static_cast<MLdouble>(*toPt)*scaleDbl + shiftDbl); 00715 } 00716 } 00717 } 00718 else{ 00719 // Images have same data type: 00720 //---------------------------- 00721 // Calculate intersection of both subimages. Copy only if intersection is not empty. 00722 const SubImageBox intersection = SubImageBox::intersect(typedFromImg.getBox(),getBox()); 00723 if (!intersection.isEmpty()){ 00724 00725 // Check data pointers and print errors if necessary. 00726 _ML_CHECK_SUBIMAGE_DATA_POINTERS(typedFromImg.getData(), getData()); 00727 00728 ImageVector p; 00729 const FROM_DATATYPE *fromPt = NULL; 00730 DATATYPE *toPt = NULL, 00731 *toPt_ = NULL, 00732 *toPtEnd = NULL; 00733 const ImageVector fromStr = typedFromImg.getStride(); 00734 const ImageVector toStr = getStride(); 00735 const MLint dist = intersection.v2.x - intersection.v1.x; 00736 const MLint size_x = dist+1; 00737 const MLint bytesize_x = size_x * MLSizeOf(getDataType()); 00738 00739 // Traverse all 6 dimensions. 00740 for (p.u=intersection.v1.u; p.u<=intersection.v2.u; ++p.u){ 00741 for (p.t=intersection.v1.t; p.t<=intersection.v2.t; ++p.t){ 00742 for (p.c=intersection.v1.c; p.c<=intersection.v2.c; ++p.c){ 00743 for (p.z=intersection.v1.z; p.z<=intersection.v2.z; ++p.z){ 00744 00745 // Get start position to each slice of data. 00746 const ImageVector pos(intersection.v1.x, intersection.v1.y, p.z, p.c, p.t, p.u); 00747 fromPt = typedFromImg.getImagePointer(pos); 00748 toPt = getImagePointer(pos); 00749 ML_CHECK_THROW(fromPt); 00750 ML_CHECK_THROW(toPt); 00751 00752 for (p.y=intersection.v1.y; p.y<=intersection.v2.y; ++p.y,fromPt+=fromStr.y,toPt+=toStr.y){ 00753 00754 // Copy buffer to target buffer. Below we work only on one buffer for rescaling. 00755 memcpy(toPt, fromPt, bytesize_x); 00756 toPt_ = toPt; 00757 00758 if (!isDTScalarType){ 00759 // See description in upper case "if (getDataType()==typedFromImg.getDataType())". 00760 for (toPtEnd = toPt_+size_x; 00761 toPt_<toPtEnd; 00762 ++toPt_){ 00763 *toPt_=static_cast<DATATYPE>(static_cast<DATATYPE>(*toPt_)*scaleDbl + shiftDbl); 00764 } 00765 } 00766 else{ 00767 for (toPtEnd = toPt_+size_x; 00768 toPt_<toPtEnd; 00769 ++toPt_){ 00770 *toPt_=static_cast<DATATYPE>(static_cast<MLdouble>(*toPt_)*scaleDbl + shiftDbl); 00771 } 00772 } 00773 } 00774 } 00775 } 00776 } 00777 } 00778 } // if (!intersection.isEmpty()) 00779 } // else 00780 } // if (getDataType()==typedFromImg.getDataType()) 00781 00782 // Images have different data type: 00783 //--------------------------------- 00784 else{ 00785 // Copy overlap of both subimages and copy only if it is not empty. 00786 const SubImageBox intersection = SubImageBox::intersect(typedFromImg.getBox(),getBox()); 00787 if (!intersection.isEmpty()){ 00788 00789 // Check data pointers and print errors if necessary. 00790 _ML_CHECK_SUBIMAGE_DATA_POINTERS(typedFromImg.getData(), getData()); 00791 00792 ImageVector p; 00793 const FROM_DATATYPE *fromPt = NULL; 00794 DATATYPE *toPt = NULL; 00795 00796 // Traverse all 6 dimensions. 00797 for (p.u=intersection.v1.u; p.u<=intersection.v2.u; ++p.u){ 00798 for (p.t=intersection.v1.t; p.t<=intersection.v2.t; ++p.t){ 00799 for (p.c=intersection.v1.c; p.c<=intersection.v2.c; ++p.c){ 00800 for (p.z=intersection.v1.z; p.z<=intersection.v2.z; ++p.z){ 00801 for (p.y=intersection.v1.y; p.y<=intersection.v2.y; ++p.y){ 00802 00803 // Get start position to each slice of data. 00804 const ImageVector pos(intersection.v1.x,p.y,p.z,p.c,p.t,p.u); 00805 fromPt = typedFromImg.getImagePointer(pos); 00806 toPt = getImagePointer(pos); 00807 const MLint startX = intersection.v1.x; 00808 const MLint endX = intersection.v2.x; 00809 00810 if (!isFDTScalarType){ 00811 // When we work with extended types we must avoid to change to double during calculations since 00812 // that causes information loss. In normal case we remain in double. 00813 for (p.x = startX; p.x <= endX; ++p.x, ++fromPt, ++toPt){ 00814 *toPt=static_cast<DATATYPE>(static_cast<FROM_DATATYPE>(*fromPt)*scaleDbl + shiftDbl); 00815 } 00816 } 00817 else{ 00818 for (p.x = startX; p.x <= endX; ++p.x, ++fromPt, ++toPt){ 00819 *toPt=static_cast<DATATYPE>(static_cast<MLdouble>(*fromPt)*scaleDbl + shiftDbl); 00820 } 00821 } 00822 } 00823 } 00824 } 00825 } 00826 } // for (p.u) 00827 00828 } // if (!intersection.isEmpty()) 00829 00830 } // else of if (getDataType()==typedFromImg.getDataType()) 00831 } 00832 ML_CATCH_RETHROW; 00833 } 00834 00835 00837 00838 00839 //------------------------------------------------------------------------------------------- 00841 00842 //------------------------------------------------------------------------------------------- 00843 00844 //--------------------------------------------------------------------------- 00846 //--------------------------------------------------------------------------- 00847 inline void fill(DATATYPE value) 00848 { 00849 ML_TRACE_IN( "TSubImage::fill( )" ); 00850 ML_TRY 00851 { 00852 ML_CHECK_THROW(_data); 00853 00854 const DATATYPE* dataEnd = static_cast<DATATYPE*>(_data) + getNumVoxels(); 00855 00856 for (DATATYPE* i = static_cast<DATATYPE*>(_data); i<dataEnd; ++i){ *i=value; } 00857 } 00858 ML_CATCH_RETHROW; 00859 }; 00860 00861 00862 //------------------------------------------------------------------------------------------- 00868 //------------------------------------------------------------------------------------------- 00869 inline void fillBordersWithValue(const SubImageBox& box, DATATYPE fillValue) 00870 { 00871 SubImage::fillBordersWithTypeData(box, reinterpret_cast<const MLTypeData*>(&fillValue)); 00872 } 00873 00874 //------------------------------------------------------------------------------------------- 00877 //------------------------------------------------------------------------------------------- 00878 inline void fillInvalidRegionWithValue(DATATYPE value) { 00879 fillBordersWithValue(getValidRegion(), value); 00880 } 00881 00882 //------------------------------------------------------------------------------------------- 00886 //------------------------------------------------------------------------------------------- 00887 inline void fillInvalidRegionWithBorderValues() { 00888 fillBordersWithBorderValues(getValidRegion()); 00889 } 00890 00892 00893 #ifdef ML_DEPRECATED 00894 00896 00897 00898 public: 00899 00902 inline ML_DEPRECATED const DATATYPE* getSubImgPos(const ImageVector &p) const { return getSubImagePointer(p); } 00905 inline ML_DEPRECATED DATATYPE* getSubImgPos(const ImageVector &p) { return getSubImagePointer(p); } 00908 inline ML_DEPRECATED const DATATYPE* getSubImgPos(MLint x, MLint y, MLint z) const { return getSubImagePointer(x, y, z); } 00911 inline ML_DEPRECATED DATATYPE* getSubImgPos(MLint x, MLint y, MLint z) { return getSubImagePointer(x, y, z); } 00914 inline ML_DEPRECATED const DATATYPE* getImgPos(const ImageVector &p) const { return getImagePointer(p); } 00917 inline ML_DEPRECATED DATATYPE* getImgPos(const ImageVector &p) { return getImagePointer(p); } 00920 inline ML_DEPRECATED const DATATYPE* getImgPos(MLint x, MLint y, MLint z) const { return getImagePointer(x, y, z); } 00923 inline ML_DEPRECATED DATATYPE* getImgPos(MLint x, MLint y, MLint z) { return getImagePointer(x, y, z); } 00926 inline ML_DEPRECATED ImageVector getSubImgCoords(DATATYPE *pos) const { return convertPointerToSubImagePosition(pos); } 00929 inline ML_DEPRECATED void getSubImgCoords(DATATYPE *pos, MLint *x, MLint *y, MLint *z) const { convertPointerToSubImagePosition(pos, x, y, z); } 00932 inline ML_DEPRECATED ImageVector getImgCoords(DATATYPE *pos) const { return convertPointerToImagePosition(pos); } 00935 inline ML_DEPRECATED void getImgCoords(DATATYPE *pos, MLint *x, MLint *y, MLint *z) const { convertPointerToImagePosition(pos, x, y, z); } 00938 inline ML_DEPRECATED void setSubImgVal(const ImageVector& p, DATATYPE val) { setSubImageValue(p, val); } 00941 inline ML_DEPRECATED DATATYPE getSubImgVal(const ImageVector& p) const { return getSubImageValue(p); } 00944 inline ML_DEPRECATED void setSubImgVal(MLint x, MLint y, DATATYPE val) { setSubImageValue(x, y, val); } 00947 inline ML_DEPRECATED DATATYPE getSubImgVal(MLint x, MLint y) const { return getSubImageValue(x, y); } 00950 inline ML_DEPRECATED void setSubImgVal(MLint x, MLint y, MLint z, DATATYPE val){ setSubImageValue(x, y, z, val); } 00953 inline ML_DEPRECATED DATATYPE getSubImgVal(MLint x, MLint y, MLint z) const { return getSubImageValue(x, y, z); } 00956 inline ML_DEPRECATED void setImgVal(const ImageVector& p, DATATYPE val) { setImageValue(p, val); } 00959 inline ML_DEPRECATED DATATYPE getImgVal(const ImageVector& p) const { return getImageValue(p); } 00962 inline ML_DEPRECATED void setImgVal(MLint x, MLint y, DATATYPE val) { setImageValue(x, y, val); } 00965 inline ML_DEPRECATED DATATYPE getImgVal(MLint x, MLint y) const { return getImageValue(x, y); } 00968 inline ML_DEPRECATED void setImgVal(MLint x, MLint y, MLint z, DATATYPE val){ setImageValue(x, y, z, val); } 00971 inline ML_DEPRECATED DATATYPE getImgVal(MLint x, MLint y, MLint z) const { return getImageValue(x, y, z); } 00974 inline ML_DEPRECATED MLint calcMinMax(DATATYPE &minVal, DATATYPE &maxVal, const SubImageBox * const validBox=NULL) const { return calculateMinMax(minVal, maxVal, validBox); } 00977 template <typename FROM_DATATYPE> 00978 ML_DEPRECATED void copySubImg(const TSubImage<FROM_DATATYPE> &typedFromImg) { copySubImage(typedFromImg); } 00981 template <typename FROM_DATATYPE> 00982 ML_DEPRECATED void copySubImg(const TSubImage<FROM_DATATYPE> &typedFromImg, const ScaleShiftData& scaleShiftData) { copySubImage(typedFromImg, scaleShiftData); } 00985 inline ML_DEPRECATED void fillSubImg(DATATYPE value) { fill(value);} 00986 00989 inline ML_DEPRECATED void fillBordersWithClampedInputValues(const SubImageBox& box) { fillBordersWithBorderValues(box); } 00990 00993 inline ML_DEPRECATED void fillBordersWithFillValue(const SubImageBox& box, DATATYPE value) { fillBordersWithValue(box, value); } 00994 00996 00997 #endif // ML_DEPRECATED 00998 00999 }; 01000 01001 #ifdef ML_DEPRECATED 01002 01003 01004 01005 01006 #define TSubImg TSubImage 01007 01008 #if defined(WIN32) && defined(ML_WARN_DEPRECATED) 01009 #pragma deprecated("TSubImg") 01010 #endif 01011 01013 #endif // ML_DEPRECATED 01014 01015 01016 //--------------------------------------------------------------------------- 01018 //--------------------------------------------------------------------------- 01019 template <typename DATATYPE> 01020 class TSubImageCursorBase { 01021 01022 protected: 01023 01024 TSubImageCursorBase(const TSubImage<DATATYPE>& subImage) { 01025 _data = const_cast<DATATYPE*>(subImage.getData()); 01026 _subImageOffset = subImage.getBox().v1; 01027 _stride = subImage.getStride(); 01028 _cursor = _data; 01029 } 01030 01031 public: 01032 01033 //--------------------------------------------------------------------------- 01035 01036 //--------------------------------------------------------------------------- 01039 inline void setSubImagePosition(const ImageVector& position) { _cursor = _data+ImageVector::dot(position,_stride); } 01042 inline void setSubImagePosition(MLint x, MLint y, MLint z) { _cursor = _data+_stride.x*x+_stride.y*y+_stride.z*z; } 01045 inline void setImagePosition(const ImageVector& position) { _cursor = _data + _ML_TSUBIMG_SUBDOT6(position,_subImageOffset,_stride); } 01048 inline void setImagePosition(MLint x, MLint y, MLint z) { _cursor = _data+ + _ML_TSUBIMG_SUBDOT3(x,y,z,_subImageOffset,_stride); } 01050 inline void setPosition(const DATATYPE *pointer) { _cursor = const_cast<DATATYPE*>(pointer); } 01052 inline void moveByOffset(const ImageVector& offset) { _cursor += ImageVector::dot(offset,_stride); } 01054 inline void moveByOffset(MLint x, MLint y, MLint z) { _cursor += _stride.x*x+_stride.y*y+_stride.z*z; } 01056 inline void moveX() { _cursor += _stride.x; } 01058 inline void moveY() { _cursor += _stride.y; } 01060 inline void moveZ() { _cursor += _stride.z; } 01062 inline void moveC() { _cursor += _stride.c; } 01064 inline void moveT() { _cursor += _stride.t; } 01066 inline void moveU() { _cursor += _stride.u; } 01068 inline void reverseMoveX() { _cursor -= _stride.x; } 01070 inline void reverseMoveY() { _cursor -= _stride.y; } 01072 inline void reverseMoveZ() { _cursor -= _stride.z; } 01074 inline void reverseMoveC() { _cursor -= _stride.c; } 01076 inline void reverseMoveT() { _cursor -= _stride.t; } 01078 inline void reverseMoveU() { _cursor -= _stride.u; } 01079 01081 01082 //--------------------------------------------------------------------------- 01084 01085 // Note: All these functions do not need explicit 64 bit arithmetic, because 01086 // pointer arithmetic always goes from valid address area to another 01087 // valid address area even on 32 systems and calculations do not fall 01088 // outside valid ranges. 01089 //--------------------------------------------------------------------------- 01091 inline DATATYPE getValue() const { return *(_cursor); } 01092 01094 inline DATATYPE getValueWithOffset(const ImageVector& offset) const { return *(_cursor+ImageVector::dot(offset,_stride)); } 01095 01097 inline DATATYPE getValueWithOffset(MLint dx, MLint dy, MLint dz) const { return *(_cursor+_stride.x*dx+_stride.y*dy+_stride.z*dz); } 01098 01100 01101 protected: 01103 DATATYPE* _data; 01105 ImageVector _subImageOffset; 01107 ImageVector _stride; 01109 DATATYPE* _cursor; 01110 01111 01112 #ifdef ML_DEPRECATED 01113 01115 01116 01117 public: 01118 01121 inline ML_DEPRECATED void setCursorSubImgPos(const ImageVector& p) { setSubImagePosition(p); } 01124 inline ML_DEPRECATED void setCursorSubImgPos(MLint x, MLint y, MLint z) { setSubImagePosition(x, y, z); } 01127 inline ML_DEPRECATED void setCursorImgPos(const ImageVector& p) { setImagePosition(p); } 01130 inline ML_DEPRECATED void setCursorImgPos(MLint x, MLint y, MLint z) { setImagePosition(x, y, z); } 01133 inline ML_DEPRECATED void setCursorPos(const DATATYPE *position) { setPosition(position); } 01136 inline ML_DEPRECATED void moveCursor(const ImageVector& dp) { moveByOffset(dp); } 01139 inline ML_DEPRECATED void moveCursor(MLint x, MLint y, MLint z) { moveByOffset(x, y, z); } 01142 inline ML_DEPRECATED void moveCursorX() { moveX(); } 01145 inline ML_DEPRECATED void moveCursorY() { moveY(); } 01148 inline ML_DEPRECATED void moveCursorZ() { moveZ(); } 01151 inline ML_DEPRECATED void moveCursorC() { moveC(); } 01154 inline ML_DEPRECATED void moveCursorT() { moveT(); } 01157 inline ML_DEPRECATED void moveCursorU() { moveU(); } 01160 inline ML_DEPRECATED void moveCursorBX() { reverseMoveX(); } 01163 inline ML_DEPRECATED void moveCursorBY() { reverseMoveY(); } 01166 inline ML_DEPRECATED void moveCursorBZ() { reverseMoveZ(); } 01169 inline ML_DEPRECATED void moveCursorBC() { reverseMoveC(); } 01172 inline ML_DEPRECATED void moveCursorBT() { reverseMoveT(); } 01175 inline ML_DEPRECATED void moveCursorBU() { reverseMoveU(); } 01178 inline DATATYPE getCursorVal() const { return getValue(); } 01181 inline DATATYPE getCursorVal(const ImageVector& dp) const { return getValueWithOffset(dp); } 01184 inline DATATYPE getCursorVal(MLint dx, MLint dy, MLint dz) const { return getValueWithOffset(dx, dy, dz); } 01185 01187 01188 #endif // ML_DEPRECATED 01189 01190 }; 01191 01192 //--------------------------------------------------------------------------- 01195 //--------------------------------------------------------------------------- 01196 template <typename DATATYPE> 01197 class ConstTSubImageCursor : public TSubImageCursorBase<DATATYPE> { 01198 01199 typedef TSubImageCursorBase<DATATYPE> T; 01200 01201 public: 01202 ConstTSubImageCursor(const TSubImage<DATATYPE>& subImage) : TSubImageCursorBase<DATATYPE>(subImage) { 01203 } 01204 01205 //--------------------------------------------------------------------------- 01207 01208 01209 01210 inline const DATATYPE* getPointer() const { return T::_cursor; } 01212 inline const DATATYPE* getPointerWithOffset(const ImageVector& offset) const { return T::_cursor+ImageVector::dot(offset,T::_stride); } 01214 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); } 01216 01217 01218 #ifdef ML_DEPRECATED 01219 01221 01222 01223 public: 01224 01227 inline ML_DEPRECATED const DATATYPE* getCursorPos() const { return getPointer(); } 01230 inline ML_DEPRECATED const DATATYPE* getCursorPos(const ImageVector& dp) const { return getPointerWithOffset(dp); } 01233 inline ML_DEPRECATED const DATATYPE* getCursorPos(MLint dx, MLint dy, MLint dz) const { return getPointerWithOffset(dx, dy, dz); } 01234 01236 01237 #endif // ML_DEPRECATED 01238 01239 }; 01240 01241 #ifdef ML_DEPRECATED 01242 01243 01244 01245 01246 #define ConstTSubImgCursor ConstTSubImageCursor 01247 01248 #if defined(WIN32) && defined(ML_WARN_DEPRECATED) 01249 #pragma deprecated("ConstTSubImgCursor") 01250 #endif 01251 01253 #endif // ML_DEPRECATED 01254 01255 01256 //--------------------------------------------------------------------------- 01259 //--------------------------------------------------------------------------- 01260 template <typename DATATYPE> 01261 class TSubImageCursor : public TSubImageCursorBase<DATATYPE> { 01262 01263 typedef TSubImageCursorBase<DATATYPE> T; 01264 01265 public: 01266 01267 TSubImageCursor(TSubImage<DATATYPE>& subImage) : TSubImageCursorBase<DATATYPE>(subImage) { 01268 } 01269 01270 //--------------------------------------------------------------------------- 01272 01273 01274 01275 inline DATATYPE* getPointer() const { return T::_cursor; } 01277 inline DATATYPE* getPointerWithOffset(const ImageVector& offset) const { return T::_cursor+ImageVector::dot(offset,T::_stride); } 01279 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); } 01281 01282 //--------------------------------------------------------------------------- 01284 01285 // Note: All these functions do not need explicit 64 bit arithmetic, because 01286 // pointer arithmetic always goes from valid address area to another 01287 // valid address area even on 32 systems and calculations do not fall 01288 // outside valid ranges. 01289 //--------------------------------------------------------------------------- 01291 inline void setValue(DATATYPE value) const { *(T::_cursor) = value; } 01293 inline void setValueWithOffset(const ImageVector& offset, DATATYPE value) const { *(T::_cursor+ImageVector::dot(offset,T::_stride))=value; } 01295 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; } 01297 01298 #ifdef ML_DEPRECATED 01299 01301 01302 01303 public: 01304 01307 inline ML_DEPRECATED DATATYPE* getCursorPos() const { return getPointer(); } 01310 inline ML_DEPRECATED DATATYPE* getCursorPos(const ImageVector& dp) const { return getPointerWithOffset(dp); } 01313 inline ML_DEPRECATED DATATYPE* getCursorPos(MLint dx, MLint dy, MLint dz) const { return getPointerWithOffset(dx, dy, dz); } 01316 inline ML_DEPRECATED void setCursorVal(DATATYPE val) const { setValue(val); } 01319 inline ML_DEPRECATED void setCursorVal(const ImageVector& dp, DATATYPE val) const { setValueWithOffset(dp, val); } 01322 inline ML_DEPRECATED void setCursorVal(MLint dx, MLint dy, MLint dz, DATATYPE val) const { setValueWithOffset(dx, dy, dz, val); } 01323 01325 01326 #endif // ML_DEPRECATED 01327 01328 }; 01329 01330 #ifdef ML_DEPRECATED 01331 01332 01333 01334 01335 #define TSubImgCursor TSubImageCursor 01336 01337 #if defined(WIN32) && defined(ML_WARN_DEPRECATED) 01338 #pragma deprecated("TSubImgCursor") 01339 #endif 01340 01342 #endif // ML_DEPRECATED 01343 01344 01345 //------------------------------------------------------------------------- 01348 //------------------------------------------------------------------------- 01349 template <typename DATATYPE> 01350 class TSubImageWithCursor : public TSubImage<DATATYPE> 01351 { 01352 typedef TSubImage<DATATYPE> T; 01353 01354 public: 01356 TSubImageWithCursor():TSubImage<DATATYPE>(), _cursor(NULL) 01357 { 01358 } 01360 TSubImageWithCursor(const TSubImage<DATATYPE>& subImage):TSubImage<DATATYPE>(subImage), _cursor(NULL) 01361 { 01362 } 01363 01365 TSubImageWithCursor(const SubImage& subImage):TSubImage<DATATYPE>(subImage), _cursor(NULL) 01366 { 01367 } 01368 01370 TSubImageWithCursor(const TSubImageWithCursor& subImage):TSubImage<DATATYPE>(subImage),_cursor(subImage._cursor) 01371 { 01372 } 01373 01376 inline TSubImageWithCursor &operator=(const TSubImageWithCursor<DATATYPE> &tSubImg) 01377 { 01378 ML_TRACE_IN_TIME_CRITICAL( "TSubImageWithCursor::operator=( )" ); 01379 ML_TRY 01380 { 01381 TSubImage<DATATYPE>::operator=(tSubImg); 01382 _cursor = tSubImg._cursor; 01383 return *this; 01384 } 01385 ML_CATCH_RETHROW; 01386 } 01387 01388 //--------------------------------------------------------------------------- 01390 01391 //--------------------------------------------------------------------------- 01394 inline void setCursorSubImagePosition(const ImageVector& position) { _cursor = static_cast<DATATYPE*>(T::_data)+ImageVector::dot(position,T::_stride); } 01397 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; } 01400 inline void setCursorImagePosition(const ImageVector& position) { _cursor = static_cast<DATATYPE*>(T::_data)+ _ML_TSUBIMG_SUBDOT6(position, T::_box.v1 ,T::_stride); } 01403 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); } 01405 inline void setCursorPosition(const DATATYPE* pointer) { _cursor = const_cast<DATATYPE*>(pointer); } 01407 inline void moveCursorByOffset(const ImageVector& offset) { _cursor += ImageVector::dot(offset,T::_stride); } 01409 inline void moveCursorByOffset(MLint x, MLint y, MLint z) { _cursor += T::_stride.x*x+T::_stride.y*y+T::_stride.z*z; } 01411 inline void moveCursorX() { _cursor += T::_stride.x; } 01413 inline void moveCursorY() { _cursor += T::_stride.y; } 01415 inline void moveCursorZ() { _cursor += T::_stride.z; } 01417 inline void moveCursorC() { _cursor += T::_stride.c; } 01419 inline void moveCursorT() { _cursor += T::_stride.t; } 01421 inline void moveCursorU() { _cursor += T::_stride.u; } 01423 inline void reverseMoveCursorX() { _cursor -= T::_stride.x; } 01425 inline void reverseMoveCursorY() { _cursor -= T::_stride.y; } 01427 inline void reverseMoveCursorZ() { _cursor -= T::_stride.z; } 01429 inline void reverseMoveCursorC() { _cursor -= T::_stride.c; } 01431 inline void reverseMoveCursorT() { _cursor -= T::_stride.t; } 01433 inline void reverseMoveCursorU() { _cursor -= T::_stride.u; } 01434 01436 01437 //--------------------------------------------------------------------------- 01439 01440 // Note: All these functions do not need explicit 64 bit arithmetic, because 01441 // pointer arithmetic always goes from valid address area to another 01442 // valid address area even on 32 systems and calculations do not fall 01443 // outside valid ranges. 01444 //--------------------------------------------------------------------------- 01446 inline DATATYPE getCursorValue() const { return *(_cursor); } 01448 inline DATATYPE getCursorValueWithOffset(const ImageVector& offset) const { return *(_cursor+ImageVector::dot(offset,T::_stride)); } 01450 inline DATATYPE getCursorValueWithOffset(MLint dx, MLint dy, MLint dz) const { return *(_cursor+T::_stride.x*dx+T::_stride.y*dy+T::_stride.z*dz); } 01451 01453 01454 //--------------------------------------------------------------------------- 01456 01457 01458 01459 inline DATATYPE* getCursorPointer() const { return _cursor; } 01461 inline DATATYPE* getCursorPointerWithOffset(const ImageVector& offset) const { return _cursor+ImageVector::dot(offset,T::_stride); } 01463 inline DATATYPE* getCursorPointerWithOffset(MLint dx, MLint dy, MLint dz) const { return (_cursor+T::_stride.x*dx+T::_stride.y*dy+T::_stride.z*dz); } 01465 01466 //--------------------------------------------------------------------------- 01468 01469 // Note: All these functions do not need explicit 64 bit arithmetic, because 01470 // pointer arithmetic always goes from valid address area to another 01471 // valid address area even on 32 systems and calculations do not fall 01472 // outside valid ranges. 01473 //--------------------------------------------------------------------------- 01475 inline void setCursorValue(DATATYPE value) { *(_cursor) = value; } 01477 inline void setCursorValueWithOffset(const ImageVector& offset, DATATYPE value) { *(_cursor+ImageVector::dot(offset,T::_stride))=value; } 01479 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; } 01480 01482 01483 private: 01485 DATATYPE* _cursor; 01486 01487 01488 #ifdef ML_DEPRECATED 01489 01491 01492 01493 public: 01494 01497 inline ML_DEPRECATED void setCursorSubImgPos(const ImageVector& p) { setCursorSubImagePosition(p); } 01500 inline ML_DEPRECATED void setCursorSubImgPos(MLint x, MLint y, MLint z) { setCursorSubImagePosition(x, y, z); } 01503 inline ML_DEPRECATED void setCursorImgPos(const ImageVector& p) { setCursorImagePosition(p); } 01506 inline ML_DEPRECATED void setCursorImgPos(MLint x, MLint y, MLint z) { setCursorImagePosition(x, y, z); } 01509 inline ML_DEPRECATED void setCursorPos(const DATATYPE* position) { setCursorPosition(position); } 01512 inline ML_DEPRECATED void moveCursor(const ImageVector& dp) { moveCursorByOffset(dp); } 01515 inline ML_DEPRECATED void moveCursor(MLint x, MLint y, MLint z) { moveCursorByOffset(x, y, z); } 01518 inline ML_DEPRECATED void moveCursorBX() { reverseMoveCursorX(); } 01521 inline ML_DEPRECATED void moveCursorBY() { reverseMoveCursorY(); } 01524 inline ML_DEPRECATED void moveCursorBZ() { reverseMoveCursorZ(); } 01527 inline ML_DEPRECATED void moveCursorBC() { reverseMoveCursorC(); } 01530 inline ML_DEPRECATED void moveCursorBT() { reverseMoveCursorT(); } 01533 inline ML_DEPRECATED void moveCursorBU() { reverseMoveCursorU(); } 01536 inline ML_DEPRECATED DATATYPE getCursorVal() const { return getCursorValue(); } 01539 inline ML_DEPRECATED DATATYPE getCursorVal(const ImageVector& dp) const { return getCursorValueWithOffset(dp); } 01542 inline ML_DEPRECATED DATATYPE getCursorVal(MLint dx, MLint dy, MLint dz) const { return getCursorValueWithOffset(dx, dy, dz); } 01545 inline ML_DEPRECATED DATATYPE* getCursorPos() const { return getCursorPointer(); } 01548 inline ML_DEPRECATED DATATYPE* getCursorPos(const ImageVector& dp) const { return getCursorPointerWithOffset(dp); } 01551 inline ML_DEPRECATED DATATYPE* getCursorPos(MLint dx, MLint dy, MLint dz) const { return getCursorPointerWithOffset(dx, dy, dz); } 01554 inline void setCursorVal(DATATYPE val) { setCursorValue(val); } 01557 inline void setCursorVal(const ImageVector& dp, DATATYPE val) { setCursorValueWithOffset(dp, val); } 01560 inline void setCursorVal(MLint dx, MLint dy, MLint dz, DATATYPE val) { setCursorValueWithOffset(dx, dy, dz, val); } 01561 01563 01564 #endif // ML_DEPRECATED 01565 01566 }; 01567 01568 #ifdef ML_DEPRECATED 01569 01570 01571 01572 01573 #define TSubImgWithCursor TSubImageWithCursor 01574 01575 #if defined(WIN32) && defined(ML_WARN_DEPRECATED) 01576 #pragma deprecated("TSubImgWithCursor") 01577 #endif 01578 01580 #endif // ML_DEPRECATED 01581 01582 //--------------------------------------------------------------------------- 01584 01585 01586 01587 01588 01589 01590 01591 01592 01593 //--------------------------------------------------------------------------- 01594 template <typename T> 01595 TSubImage<T>& tsubimage_cast(SubImage& subImg) 01596 { 01597 // Check whether template type and real data type match if there is valid data. 01598 if (subImg.getData() && !TypeTraits<T>::matches(subImg.getDataType()) ) 01599 { 01600 ML_PRINT_FATAL_ERROR("tsubimage_cast", ML_BAD_DATA_TYPE, 01601 "Mismatch of data type between argument and template typename."); 01602 } 01603 return *(static_cast<TSubImage<T>* >(&subImg)); 01604 } 01605 01606 template <typename T> 01607 const TSubImage<T>& tsubimage_cast(const SubImage& subImg) 01608 { 01609 // Check whether template type and real data type match if there is valid data. 01610 if (subImg.getData() && !TypeTraits<T>::matches(subImg.getDataType()) ) 01611 { 01612 ML_PRINT_FATAL_ERROR("tsubimage_cast", ML_BAD_DATA_TYPE, 01613 "Mismatch of data type between argument and template typename."); 01614 } 01615 return *(static_cast<const TSubImage<T>* >(&subImg)); 01616 } 01617 01618 template <typename T> 01619 TSubImage<T>* tsubimage_cast(SubImage* subImg) 01620 { 01621 // Check whether template type and real data type match if there is valid data. 01622 if (subImg->getData() && !TypeTraits<T>::matches(subImg->getDataType()) ) 01623 { 01624 ML_PRINT_FATAL_ERROR("tsubimage_cast", ML_BAD_DATA_TYPE, 01625 "Mismatch of data type between argument and template typename."); 01626 } 01627 return static_cast<TSubImage<T>* >(subImg); 01628 } 01629 01630 template <typename T> 01631 const TSubImage<T>* tsubimage_cast(const SubImage* subImg) 01632 { 01633 // Check whether template type and real data type match if there is valid data. 01634 if (subImg->getData() && !TypeTraits<T>::matches(subImg->getDataType()) ) 01635 { 01636 ML_PRINT_FATAL_ERROR("tsubimage_cast", ML_BAD_DATA_TYPE, 01637 "Mismatch of data type between argument and template typename."); 01638 } 01639 return static_cast<const TSubImage<T>* >(subImg); 01640 } 01641 01643 01644 #ifdef ML_DEPRECATED 01645 01648 template <typename T> 01649 TSubImage<T>* tsubimg_cast(SubImage* subImg) { return tsubimage_cast<T>(subImg); } 01650 01653 template <typename T> 01654 const TSubImage<T>* tsubimg_cast(const SubImage* subImg) { return tsubimage_cast<T>(subImg); } 01655 01658 template <typename T> 01659 TSubImage<T>& tsubimg_cast(SubImage& subImg) { return tsubimage_cast<T>(subImg); } 01660 01663 template <typename T> 01664 const TSubImage<T>& tsubimg_cast(const SubImage& subImg) { return tsubimage_cast<T>(subImg); } 01665 01666 01667 #endif 01668 01669 01670 ML_END_NAMESPACE 01671 01672 namespace std { 01673 01674 //--------------------------------------------------------------------------- 01675 // Debug printing for TSubImage. 01676 //--------------------------------------------------------------------------- 01677 01680 template <typename DATATYPE> 01681 inline ostream &operator<<(ostream &ostr, const ML_NAMESPACE::TSubImage<DATATYPE> &v) 01682 { 01683 // Get box of subimage and traverse all of its voxels. 01684 const ML_NAMESPACE::SubImageBox& box = v.getBox(); 01685 ML_NAMESPACE::ImageVector p; 01686 for (p.u=box.v1.u; p.u<=box.v2.u; ++p.u){ 01687 for (p.t=box.v1.t; p.t<=box.v2.t; ++p.t){ 01688 for (p.c=box.v1.c; p.c<=box.v2.c; ++p.c){ 01689 for (p.z=box.v1.z; p.z<=box.v2.z; ++p.z){ 01690 for (p.y=box.v1.y; p.y<=box.v2.y; ++p.y){ 01691 // Print row of voxels after a single row start position. 01692 p.x = box.v1.x; 01693 ostr << p << ": "; 01694 for (; p.x<=box.v2.x; p.x++){ 01695 ostr << v.getImageValue(p) << " "; 01696 } 01697 ostr << std::endl; 01698 } 01699 } 01700 } 01701 } 01702 } 01703 return ostr; 01704 } 01705 01706 } 01707 01708 #ifdef _MSC_VER 01709 #pragma warning(pop) 01710 #endif 01711 01712 01713 #endif //of __mlTSubImage_H 01714 01715 01716