ML Reference
MeVis/Foundation/Sources/ML/include/mlTSubImage.h
Go to the documentation of this file.
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