Image Component Library (ICL)
|
00001 /******************************************************************** 00002 ** Image Component Library (ICL) ** 00003 ** ** 00004 ** Copyright (C) 2006-2013 CITEC, University of Bielefeld ** 00005 ** Neuroinformatics Group ** 00006 ** Website: www.iclcv.org and ** 00007 ** http://opensource.cit-ec.de/projects/icl ** 00008 ** ** 00009 ** File : ICLCore/src/ICLCore/Img.h ** 00010 ** Module : ICLCore ** 00011 ** Authors: Christof Elbrechter, Michael Goetting, Robert ** 00012 ** Haschke, Andre Justus, Sergius Gaulik ** 00013 ** ** 00014 ** ** 00015 ** GNU LESSER GENERAL PUBLIC LICENSE ** 00016 ** This file may be used under the terms of the GNU Lesser General ** 00017 ** Public License version 3.0 as published by the ** 00018 ** ** 00019 ** Free Software Foundation and appearing in the file LICENSE.LGPL ** 00020 ** included in the packaging of this file. Please review the ** 00021 ** following information to ensure the license requirements will ** 00022 ** be met: http://www.gnu.org/licenses/lgpl-3.0.txt ** 00023 ** ** 00024 ** The development of this software was supported by the ** 00025 ** Excellence Cluster EXC 277 Cognitive Interaction Technology. ** 00026 ** The Excellence Cluster EXC 277 is a grant of the Deutsche ** 00027 ** Forschungsgemeinschaft (DFG) in the context of the German ** 00028 ** Excellence Initiative. ** 00029 ** ** 00030 ********************************************************************/ 00031 00032 #pragma once 00033 00034 #include <ICLUtils/SmartPtr.h> 00035 #include <ICLUtils/Exception.h> 00036 #include <ICLCore/ImgBase.h> 00037 #include <ICLCore/ImgIterator.h> 00038 #include <ICLCore/Channel.h> 00039 #include <ICLCore/PixelRef.h> 00040 #include <ICLMath/DynMatrix.h> 00041 #include <cmath> 00042 #include <algorithm> 00043 00044 00045 namespace icl { 00046 namespace core{ 00048 template<class Type> 00049 class ICLCore_API Img : public ImgBase 00050 { 00051 00052 /* this is declare as fried, because it accesses the private append function */ 00053 template<class ImgType> friend 00054 const ImgType* combineImages (const std::vector<const ImgType*>& vec, ImgBase** ppoDst); 00055 00057 00060 Img<Type>& shallowCopy(const Img<Type>& tSource); 00061 00063 00066 void append(const Img<Type> *src, int iChannel=-1); 00067 00069 00072 void append(const Img<Type> *src, const std::vector<int>& vChannels); 00073 00074 protected: 00075 00077 /* {{{ open */ 00078 00080 std::vector<utils::SmartArray<Type> > m_vecChannels; 00082 00083 /* }}} */ 00084 00086 /* {{{ open */ 00087 00089 00092 utils::SmartArray<Type> createChannel(Type *ptDataToCopy=0) const; 00093 00095 00121 int getStartIndex(int iIndex) const { return iIndex < 0 ? 0 : iIndex; } 00122 00124 00129 int getEndIndex(int iIndex) const { return iIndex < 0 ? getChannels() : iIndex+1; } 00130 00132 00133 /* }}} */ 00134 00136 /* {{{ open */ 00137 00139 00148 void normalize(int iChannel, 00149 const utils::Range<Type> &srcRange, 00150 const utils::Range<Type> &dstRange); 00151 00153 00158 void mirror(axis eAxis, int iChannel, 00159 const utils::Point& oOffset, 00160 const utils::Size& oSize); 00162 /* }}} */ 00163 00164 public: 00165 00167 static const Img<Type> null; 00168 00169 /* {{{ open */ 00171 00174 Img(const ImgParams ¶ms = ImgParams::null); 00175 00177 00181 Img(const utils::Size &size, int channels); 00182 00184 00187 Img(const utils::Size &s, format fmt); 00188 00190 00197 Img(const utils::Size &s, int channels, format fmt); 00198 00200 00211 Img(const utils::Size &size, format format, const std::vector<Type*>& vptData, 00212 bool passOwnerShip=false); 00213 00215 00226 Img(const utils::Size &size, int channels, 00227 const std::vector<Type*>& vptData, bool passOwnerShip=false); 00228 00230 00243 Img(const utils::Size &size, int channels, format fmt, 00244 const std::vector<Type*>& vptData, bool passOwnerShip=false); 00245 00247 00262 Img(const Img<Type>& tSrc); 00263 00264 00266 00278 Img(const math::DynMatrix<Type> &c1, 00279 const math::DynMatrix<Type> &c2=math::DynMatrix<Type>(), 00280 const math::DynMatrix<Type> &c3=math::DynMatrix<Type>(), 00281 const math::DynMatrix<Type> &c4=math::DynMatrix<Type>(), 00282 const math::DynMatrix<Type> &c5=math::DynMatrix<Type>()) throw (math::InvalidMatrixDimensionException); 00283 00284 00286 ~Img(); 00287 00289 bool isNull() const{ 00290 return getSize()==utils::Size::null && getChannels() == 0; 00291 } 00292 00293 00294 /* }}} */ 00295 00297 /* {{{ open */ 00298 00300 operator Img<Type>&(){ 00301 return *this; 00302 } 00303 00305 operator const Img<Type>&() const { 00306 return *this; 00307 } 00308 00310 00324 Img<Type>& operator=(const Img<Type>& tSource) { 00325 // call private const-version 00326 return this->shallowCopy (static_cast<const Img<Type>&>(tSource)); 00327 } 00328 /* 00329 #ifdef WIN32 00330 Img<Type>& operator=(const Img<Type>& tSource) { 00331 // call private const-version 00332 return this->shallowCopy (static_cast<const Img<Type>&>(tSource)); 00333 } 00334 #endif 00335 00336 #ifdef GCC_VER_423 00337 Img<Type>& operator=(const Img<Type>& tSource) { 00338 // call private const-version 00339 return this->shallowCopy (static_cast<const Img<Type>&>(tSource)); 00340 } 00341 #endif 00342 */ 00343 00345 00372 Type& operator()(int iX, int iY, int iChannel) { 00373 return const_cast<Type&>(static_cast<const Img<Type>*>(this)->operator()(iX,iY,iChannel)); 00374 } 00375 00377 const Type& operator()(int iX, int iY, int iChannel) const { 00378 return getData(iChannel)[iX+getWidth()*iY]; 00379 } 00380 00382 00387 inline PixelRef<Type> operator()(int x, int y){ 00388 return PixelRef<Type>(x,y,getWidth(),m_vecChannels); 00389 } 00390 00392 inline const PixelRef<Type> operator()(int x, int y) const{ 00393 return const_cast<Img<Type>*>(this)->operator()(x,y); 00394 } 00395 00397 00399 inline Channel<Type> operator[](int channel) { 00400 return Channel<Type>(begin(channel),getSize(),getROI()); 00401 } 00402 00404 00406 inline const Channel<Type> operator[](int channel) const { 00407 return Channel<Type>(const_cast<Type*>(begin(channel)),getSize(),getROI()); 00408 } 00409 00410 00412 float subPixelNN(float fX, float fY, int iChannel) const { 00413 return (*this)((int)fX, (int)fY, iChannel); 00414 } 00415 00417 float subPixelLIN(float fX, float fY, int iChannel) const; 00418 00420 float subPixelRA(float fX, float fY, float w, float h, int iChannel) const; 00421 float subPixelRA(const unsigned int xB, const unsigned int xE, 00422 const unsigned int yB, const unsigned int yE, 00423 const float xBMul, const float xEMul, const float BMul, const float yEMul, 00424 const Type *d, const unsigned int w) const; 00425 00427 Type operator()(float fX, float fY, int iChannel, scalemode eMode) const; 00428 00430 00431 /* }}} */ 00432 00434 /* {{{ open */ 00435 00436 /*inline <Type> operator[](int channel) throw (InvalidMatrixDimensionException){ 00437 return DynMatrix<Type>(getWidth(),getHeight(),begin(channel),false); 00438 }*/ 00439 00441 /* This function cannot be called on (0,x) or (x,0)-sized images */ 00442 inline math::DynMatrix<Type> extractDynMatrix(int channel) 00443 throw (math::InvalidMatrixDimensionException){ 00444 return math::DynMatrix<Type>(getWidth(),getHeight(),begin(channel),false); 00445 } 00447 /* This function cannot be called on (0,x) or (x,0)-sized images */ 00448 inline const math::DynMatrix<Type> extractDynMatrix(int channel) const 00449 throw (math::InvalidMatrixDimensionException){ 00450 return math::DynMatrix<Type>(getWidth(),getHeight(),const_cast<Type*>(begin(channel)),false); 00451 } 00452 00454 inline void extractChannels(Channel<Type> *dst){ 00455 ICLASSERT_RETURN(dst); 00456 for(int i=0;i<getChannels();++i){ 00457 dst[i] = (*this)[i]; 00458 } 00459 } 00460 00462 00463 inline void extractChannels(Channel<Type> *dst) const{ 00464 (void)dst; 00465 ERROR_LOG("extracting channels of a const Img into an un-const Channel\n" 00466 "is forbidden because it violates the const concept"); 00467 } 00468 00470 00471 inline void extractChannels(const Channel<Type> *dst) const{ 00472 return const_cast<Img<Type>*>(this)->extractChannels(const_cast<Channel<Type>*>(dst)); 00473 } 00474 00476 inline void extractPointers(Type **dst){ 00477 for(int i=0;i<getChannels();++i){ 00478 dst[i] = begin(i); 00479 } 00480 } 00481 00483 00484 inline void extractPointers(Type **dst) const{ 00485 (void)dst; 00486 ERROR_LOG("extracting channel data of a const Img into an un-const pointer\n" 00487 "is forbidden because it violates the const concept"); 00488 } 00489 00491 inline void extractPointers(const Type **dst) const{ 00492 for(int i=0;i<getChannels();++i){ 00493 dst[i] = begin(i); 00494 } 00495 } 00496 00497 00498 00500 00501 /* }}} */ 00502 00503 00505 /* {{{ open */ 00506 00507 virtual Img<Type> *shallowCopy(const utils::Rect &roi, 00508 const std::vector<int> &channelIndices, 00509 format fmt, 00510 utils::Time time = utils::Time::null, 00511 ImgBase **ppoDst = NULL); 00512 00525 const Img<Type> *shallowCopy(const utils::Rect &roi, 00526 const std::vector<int> &channelIndices, 00527 format fmt, 00528 utils::Time time=utils::Time::null) const{ 00529 // casting constness away is safe, because we effectively return a const Img<Type>* 00530 return const_cast<Img<Type>*>(this)->shallowCopy(roi,channelIndices,fmt,time,0); 00531 } 00532 00533 00535 00540 Img<Type> *reinterpretChannels(format newFmt, Img<Type> *poDst = NULL){ 00541 ImgBase *poDstBase = poDst; 00542 return shallowCopy(getROI(),std::vector<int>(),newFmt,getTime(),&poDstBase); 00543 } 00544 00545 00547 00551 const Img<Type> *reinterpretChannels(format newFmt){ 00552 return shallowCopy(getROI(),std::vector<int>(),newFmt,getTime()); 00553 } 00555 00566 Img<Type>* shallowCopy(const utils::Rect &roi,Img<Type>* poDst = NULL){ 00567 ImgBase *poDstBase = poDst; 00568 return shallowCopy(roi,std::vector<int>(),getFormat(),getTime(),&poDstBase); 00569 } 00570 00572 00581 const Img<Type>* shallowCopy(const utils::Rect& roi) const { 00582 // casting constness away is safe, because we effectively return a const Img<Type>* 00583 return const_cast<Img<Type>*>(this)->shallowCopy(roi,0); 00584 } 00585 00586 00588 00597 Img<Type>* selectChannels (const std::vector<int>& channelIndices, Img<Type>* poDst=0){ 00598 ImgBase *poDstBase = poDst; 00599 return shallowCopy(getROI(),channelIndices,formatMatrix,getTime(),&poDstBase); 00600 } 00601 00603 00610 Img<Type> *selectChannel(int channelIndex, Img<Type> *poDst=0){ 00611 ICLASSERT_RETURN_VAL(validChannel(channelIndex), 0); 00612 std::vector<int> v(1); v[0]= channelIndex; 00613 return selectChannels(v,poDst); 00614 } 00616 00619 const Img<Type>* selectChannels (const std::vector<int>& channelIndices) const { 00620 // casting constness away is safe, because we effectively return a const Img<Type>* 00621 return const_cast<Img<Type>*>(this)->selectChannels(channelIndices, 0); 00622 } 00623 00625 00631 const Img<Type> *selectChannel(int channelIndex) const{ 00632 ICLASSERT_RETURN_VAL(validChannel(channelIndex), 0); 00633 std::vector<int> v(1); v[0]= channelIndex; return selectChannels(v); 00634 } 00635 00636 //------------------------------------------------------------------------------ 00637 //------------------------------------------------------------------------------ 00638 //------------------------------------------------------------------------------ 00639 00640 00641 00642 00643 00645 00646 virtual Img<Type>* deepCopy(ImgBase** ppoDst=0) const; 00647 00649 00656 Img<Type> *deepCopy(Img<Type> *poDst) const; 00657 00659 00660 virtual Img<Type> *deepCopyROI(ImgBase **ppoDst=0) const; 00661 00662 00664 00674 Img<Type> *deepCopyROI(Img<Type> *poDst) const; 00675 00677 /* }}} */ 00678 00680 /* {{{ open */ 00681 00683 00684 virtual Img<Type> *scaledCopy(const utils::Size &newSize, scalemode eScaleMode=interpolateNN) const; 00685 00687 00688 virtual Img<Type> *scaledCopy(ImgBase **ppoDst=0, scalemode eScaleMode=interpolateNN) const; 00689 00690 00692 00698 Img<Type> *scaledCopy(Img<Type> *poDst, scalemode eScaleMode=interpolateNN) const; 00699 00701 00702 virtual Img<Type> *scaledCopyROI(const utils::Size &newSize, scalemode eScaleMode=interpolateNN) const; 00703 00705 00706 virtual Img<Type> *scaledCopyROI(ImgBase **ppoDst=0, scalemode eScaleMode=interpolateNN) const; 00707 00709 00715 Img<Type> *scaledCopyROI(Img<Type> *poDst, scalemode eScaleMode=interpolateNN) const; 00716 00718 /* }}} */ 00719 00721 /* {{{ open */ 00722 00724 00725 virtual void detach(int iIndex = -1); 00726 00728 00735 inline Img<Type> detached() const { 00736 Img<Type> detachedCopy = *this; 00737 detachedCopy.detach(); 00738 return detachedCopy; 00739 } 00740 00742 00743 virtual void removeChannel(int iChannel); 00744 00746 00756 void append(Img<Type> *src, int iChannel=-1) { 00757 // call private const-version 00758 this->append (static_cast<const Img<Type>*>(src), iChannel); 00759 } 00760 00762 00764 void append(Img<Type> *src, const std::vector<int>& vChannels) { 00765 // call private const-version 00766 this->append (static_cast<const Img<Type>*>(src), vChannels); 00767 } 00768 00770 00772 Img<Type> extractChannelImg(int index); 00773 00775 00777 const Img<Type> extractChannelImg(int index) const; 00778 00780 00782 Img<Type> extractChannelImg(const std::vector<int> &indices); 00783 00785 00787 const Img<Type> extractChannelImg(const std::vector<int> &indices) const; 00788 00789 00791 00792 virtual void swapChannels(int iIndexA, int iIndexB); 00793 00795 00800 void replaceChannel(int iThisIndex, Img<Type> *poOtherImg, int iOtherIndex); 00801 00803 00804 virtual void setChannels(int iNewNumChannels); 00805 00807 00808 virtual void setSize(const utils::Size &s); 00809 00811 00812 /* }}} */ 00813 00815 /* {{{ open */ 00816 00818 00822 Type getMax(int iChannel, utils::Point *coords=0) const; 00823 00825 00829 Type getMin(int iChannel, utils::Point *coords=0) const; 00830 00831 00833 Type getMin() const; 00834 00836 Type getMax() const; 00837 00839 00845 const utils::Range<Type> getMinMax(int iChannel, 00846 utils::Point *minCoords=0, 00847 utils::Point *maxCoords=0) const; 00848 00850 const utils::Range<Type> getMinMax() const; 00851 00853 00854 virtual int getLineStep() const{ 00855 return getSize().width*sizeof(Type); 00856 } 00857 00859 00864 Type* getData(int iChannel) { 00865 return const_cast<Type*>(static_cast<const Img<Type>*>(this)->getData(iChannel)); 00866 } 00867 00869 00870 const Type* getData(int iChannel) const { 00871 FUNCTION_LOG(""); 00872 ICLASSERT_RETURN_VAL(validChannel(iChannel), 0); 00873 return m_vecChannels[iChannel].get(); 00874 } 00875 00877 00896 Type* getROIData(int iChannel) { 00897 return const_cast<Type*>(static_cast<const Img<Type>*>(this)->getROIData(iChannel)); 00898 } 00899 00901 00902 const Type* getROIData(int iChannel) const { 00903 FUNCTION_LOG(""); 00904 ICLASSERT_RETURN_VAL(validChannel(iChannel),0); 00905 return getData(iChannel) + m_oParams.getPixelOffset(); 00906 } 00907 00909 00918 Type* getROIData(int iChannel, const utils::Point &p) { 00919 return const_cast<Type*>(static_cast<const Img<Type>*>(this)->getROIData(iChannel, p)); 00920 } 00922 00923 const Type* getROIData(int iChannel, const utils::Point &p) const { 00924 FUNCTION_LOG(""); 00925 ICLASSERT_RETURN_VAL(validChannel(iChannel),0); 00926 return getData(iChannel) + p.x + (p.y * getWidth()); 00927 } 00928 00930 00931 virtual void* getDataPtr(int iChannel){ 00932 return getData(iChannel); 00933 } 00934 00936 00937 virtual const void* getDataPtr(int iChannel) const{ 00938 return getData(iChannel); 00939 } 00940 00942 00943 /* }}} */ 00944 00946 /* {{{ open */ 00947 00948 00950 00976 template<typename UnaryFunction> 00977 inline Img<Type> &forEach_C(UnaryFunction f, int channel){ 00978 ICLASSERT_RETURN_VAL(validChannel(channel),*this); 00979 if(hasFullROI()){ 00980 std::for_each<Type*,UnaryFunction>(getData(channel),getData(channel)+getDim(),f); 00981 }else{ 00982 const_roi_iterator end = endROI(channel); 00983 for(ImgIterator<Type> it = beginROI(channel); it != end; it.incRow()){ 00984 std::for_each<Type*,UnaryFunction>(&(*it),&(*it)+it.getSubRectWidth(),f); 00985 } 00986 } 00987 return *this; 00988 } 00989 00991 01010 template<typename UnaryFunction> 01011 inline Img<Type> &forEach(UnaryFunction f){ 01012 for(int c=0;c<getChannels();++c){ 01013 forEach_C(f,c); 01014 } 01015 return *this; 01016 } 01017 01019 01042 template<typename UnaryFunction, class dstType> 01043 inline Img<dstType> &transform_C(UnaryFunction f, int srcChannel, int dstChannel, Img<dstType> &dst) const{ 01044 ICLASSERT_RETURN_VAL(getROISize() == dst.getROISize(),dst); 01045 ICLASSERT_RETURN_VAL(validChannel(srcChannel),dst); 01046 ICLASSERT_RETURN_VAL(dst.validChannel(dstChannel),dst); 01047 01048 if(hasFullROI() && dst.hasFullROI()){ 01049 std::transform(getData(srcChannel),getData(srcChannel)+getDim(),dst.getData(dstChannel),f); 01050 }else{ 01051 ImgIterator<dstType> itDst = dst.beginROI(dstChannel); 01052 const_roi_iterator end = endROI(srcChannel); 01053 for(const_roi_iterator it = beginROI(srcChannel); it != end; it.incRow(), itDst.incRow()){ 01054 std::transform(&(*it),&(*it)+it.getSubRectWidth(),&(*itDst),f); 01055 } 01056 } 01057 return dst; 01058 } 01059 01061 01083 template<typename UnaryFunction,class dstType> 01084 inline Img<dstType> &transform(UnaryFunction f, Img<dstType> &dst) const{ 01085 ICLASSERT_RETURN_VAL(getChannels() == dst.getChannels(),dst); 01086 for(int c=0;c<getChannels();++c){ 01087 transform_C(f,c,c,dst); 01088 } 01089 return dst; 01090 } 01091 01092 01094 01134 template<typename BinaryFunction, class dstType, class otherSrcType> 01135 inline Img<dstType> &combine_C(BinaryFunction f, 01136 int thisChannel, 01137 int otherSrcChannel, 01138 int dstChannel, 01139 const Img<otherSrcType> &otherSrc, 01140 Img<dstType> &dst) const{ 01141 ICLASSERT_RETURN_VAL(getROISize() == dst.getROISize()&& getROISize() == otherSrc.getROISize(),dst); 01142 ICLASSERT_RETURN_VAL(validChannel(thisChannel),dst); 01143 ICLASSERT_RETURN_VAL(otherSrc.validChannel(otherSrcChannel),dst); 01144 ICLASSERT_RETURN_VAL(dst.validChannel(dstChannel),dst); 01145 01146 if(hasFullROI() && dst.hasFullROI() && otherSrc.hasFullROI()){ 01147 std::transform(getData(thisChannel),getData(thisChannel)+getDim(),otherSrc.getData(otherSrcChannel),dst.getData(dstChannel),f); 01148 }else{ 01149 ImgIterator<dstType> itDst = dst.beginROI(dstChannel); 01150 const ImgIterator<otherSrcType> itOtherSrc = otherSrc.beginROI(otherSrcChannel); 01151 const_roi_iterator end = endROI(thisChannel); 01152 for(const_roi_iterator it = beginROI(thisChannel); it!=end; it.incRow(), itDst.incRow(),itOtherSrc.incRow()){ 01153 std::transform(&(*it),&(*it)+it.getROIWidth(),&(*itOtherSrc),&(*itDst),f); 01154 } 01155 } 01156 return dst; 01157 } 01158 01159 01161 01189 template<typename BinaryFunction, class dstType, class otherSrcType> 01190 inline Img<dstType> &combine(BinaryFunction f, const Img<otherSrcType> &otherSrc, Img<dstType> &dst) const{ 01191 ICLASSERT_RETURN_VAL(getChannels() == otherSrc.getChannels(),dst); 01192 ICLASSERT_RETURN_VAL(getChannels() == dst.getChannels(),dst); 01193 for(int c=0;c<getChannels();++c){ 01194 combine_C(f,c,c,c,otherSrc,dst); 01195 } 01196 return dst; 01197 } 01198 01199 01200 01201 private: 01203 template<typename Tsrc, typename Tdst, int Nsrc, int Ndst, typename ReduceFunc> 01204 static inline void reduce_arrays(const Tsrc *src[Nsrc], Tdst *dst[Ndst], unsigned int dim, ReduceFunc reduce){ 01205 for(int i=dim-1;i>=0;--i){ 01206 Tsrc tsrc[Nsrc]; 01207 Tdst tdst[Ndst]; 01208 for(int j=0;j<Nsrc;tsrc[j]=src[j][i],++j) {} 01209 reduce(tsrc,tdst); 01210 for(int j=0;j<Ndst;dst[j][i]=tdst[j],++j) {} 01211 01212 } 01213 } 01214 01215 public: 01216 01217 01219 01253 template<typename Tdst, int Nthis, int Ndst, typename ReduceFunc> 01254 void reduce_channels(Img<Tdst> &dst, ReduceFunc reduce) const { 01255 ICLASSERT_RETURN(this->getROISize() == dst.getROISize()); 01256 ICLASSERT_RETURN((Nthis > 0) && (Ndst > 0)); 01257 ICLASSERT_RETURN((this->getChannels()==Nthis) && (dst.getChannels()==Ndst)); 01258 01259 const Type *psrc[Nthis]; 01260 Tdst *pdst[Ndst]; 01261 if(this->hasFullROI() && dst.hasFullROI()){ 01262 for(int i=0;i<Nthis;psrc[i]=this->getData(i),++i) {} 01263 for(int i=0;i<Ndst;pdst[i]=dst.getData(i),++i) {} 01264 reduce_arrays<Type,Tdst,Nthis,Ndst,ReduceFunc>(psrc,pdst,this->getDim(),reduce); 01265 }else{ 01266 const_roi_iterator itSrc[Nthis]; 01267 ImgIterator<Tdst> itDst[Ndst]; 01268 for(int i=0;i<Nthis;itSrc[i]=this->beginROI(i),++i) {} 01269 for(int i=0;i<Ndst;itDst[i]=dst.beginROI(i),++i) {} 01270 01271 for(int l=this->getROI().height-1, w=this->getROI().width ;l>=0;--l){ 01272 for(int i=0;i<Nthis;itSrc[i].incRow(),++i){ 01273 psrc[i]=&(*(itSrc[i])); 01274 } 01275 for(int i=0;i<Ndst;itDst[i].incRow(),++i){ 01276 pdst[i]=&(*(itDst[i])); 01277 } 01278 reduce_arrays<Type,Tdst,Nthis,Ndst,ReduceFunc>(psrc,pdst,w,reduce); 01279 } 01280 } 01281 } 01282 01284 01287 Img<Type> *lut(const Type *lut, Img<Type> *dst = 0,int bits=8) const; 01288 01290 01291 virtual void scale(const utils::Size &s, scalemode eScaleMode=interpolateNN); 01292 01294 01295 virtual void mirror(axis eAxis, bool bOnlyROI=false); 01296 01298 01302 void clear(int iChannel = -1, Type tValue = 0, bool bROIOnly=true); 01303 01305 01321 template<class T> 01322 inline void fill(const T &value){ 01323 for(int i=0;i<getChannels();++i){ 01324 std::fill(begin(i),end(i),value); 01325 } 01326 } 01327 01329 template<class T> 01330 inline void fillChannel(int channel, const T &value){ 01331 std::fill(begin(channel),end(channel),value); 01332 } 01333 01334 01336 template<class T> 01337 inline void fillROI(const T &value){ 01338 for(int i=0;i<getChannels();++i){ 01339 std::fill(beginROI(i),endROI(i),value); 01340 } 01341 } 01342 01344 template<class T> 01345 inline void fillChannelROI(int channel, const T &value){ 01346 std::fill(beginROI(channel),endROI(channel),value); 01347 } 01348 01349 01351 01355 void normalizeAllChannels(const utils::Range<Type> &dstRange); 01356 01358 01362 void normalizeChannel(int iChannel, const utils::Range<Type> &srcRange, 01363 const utils::Range<Type> &dstRange); 01364 01366 01371 void normalizeChannel(int iChannel,const utils::Range<Type> &dstRange); 01372 01374 01377 void normalizeImg(const utils::Range<Type> &srcRange, 01378 const utils::Range<Type> &dstRange); 01379 01381 01385 void normalizeImg(const utils::Range<Type> &dstRange); 01386 01388 01389 /* }}} */ 01390 01392 /* {{{ open */ 01393 01395 typedef Type* iterator; 01396 01398 typedef const Type* const_iterator; 01399 01401 typedef ImgIterator<Type> roi_iterator; 01402 01404 typedef const ImgIterator<Type> const_roi_iterator; 01405 // old typedef constConstImgIterator<Type> const_iterator; 01406 01407 01408 01410 inline iterator begin(int channel){ 01411 return getData(channel); 01412 } 01413 01415 inline const_iterator begin(int channel) const{ 01416 return const_cast<Img<Type>*>(this)->begin(channel); 01417 } 01418 01420 iterator end(int channel){ 01421 return getData(channel)+getDim(); 01422 } 01423 01425 const_iterator end(int channel) const{ 01426 return getData(channel)+getDim(); 01427 } 01428 01430 inline roi_iterator beginROI(int channel){ 01431 ICLASSERT_RETURN_VAL(validChannel(channel), roi_iterator()); 01432 return roi_iterator(getData(channel),getWidth(),getROI()); 01433 } 01434 01436 inline const_roi_iterator beginROI(int channel) const{ 01437 ICLASSERT_RETURN_VAL(validChannel(channel), roi_iterator()); 01438 return const_cast<Img<Type>*>(this)->beginROI(channel); 01439 } 01440 01442 01443 inline roi_iterator endROI(int channel) { 01444 ICLASSERT_RETURN_VAL(validChannel(channel), roi_iterator()); 01445 return roi_iterator::create_end_roi_iterator(getData(channel),getWidth(),getROI()); 01446 } 01447 01449 inline const_roi_iterator endROI(int channel) const{ 01450 ICLASSERT_RETURN_VAL(validChannel(channel), roi_iterator()); 01451 return const_roi_iterator::create_end_roi_iterator(getData(channel),getWidth(),getROI()); 01452 } 01453 01454 01456 01467 utils::Point getLocation(const Type *p, int channel, bool relToROI=false) const; 01468 01470 01476 void printAsMatrix(const std::string &format="5.3", bool visROI=true) const; 01477 01479 01480 virtual bool isIndependent() const; 01482 01483 /* }}} */ 01484 01486 /* {{{ open */ 01487 01489 01493 virtual void fillBorder(bool setFullROI=true); 01494 01496 virtual void fillBorder(icl64f val, bool setFullROI=true); 01497 01499 01502 virtual void fillBorder(const std::vector<icl64f> &vals, bool setFullROI=true); 01503 01504 01506 01510 virtual void fillBorder(const ImgBase *src, bool setFullROI=true); 01511 01513 /* }}} */ 01514 01515 01516 };// class Img<Type> 01517 01518 01519 /* {{{ global functions */ 01520 01522 01525 template<class T> struct ICLCore_API ImgBasePtrPtr { 01527 ImgBasePtrPtr(Img<T> &i); 01528 01530 ImgBasePtrPtr(Img<T> *i); 01531 01533 01543 ~ImgBasePtrPtr(); 01544 01546 operator ImgBase** (){ return &r; } 01547 01548 private: 01550 ImgBase *o,*r,*rbef; 01551 }; 01552 01554 01584 template<class T> 01585 ImgBasePtrPtr<T> bpp(Img<T> *image) { return ImgBasePtrPtr<T>(image); } 01586 01588 01589 template<class T> 01590 ImgBasePtrPtr<T> bpp(Img<T> &image) { return ImgBasePtrPtr<T>(image); } 01591 01592 01594 01638 template<class T> 01639 static inline T p2o(T *ptr){ 01640 return *utils::SmartPtr<T>(ptr); 01641 } 01642 01644 template<class ImgType> 01645 const ImgType* combineImages(const std::vector<const ImgType*>& vec); 01646 01648 template<class ImgType> 01649 ImgType* combineImages(const std::vector<ImgType*>& vec) { 01650 return const_cast<ImgType*>(combineImages(reinterpret_cast<const std::vector<const ImgType*>&>(vec))); 01651 } 01652 01653 /* {{{ deepCopyChannel */ 01655 template<class T> 01656 inline void deepCopyChannel(const Img<T> *src, int srcC, Img<T> *dst, int dstC){ 01657 FUNCTION_LOG(""); 01658 ICLASSERT_RETURN( src && dst ); 01659 ICLASSERT_RETURN( src->getSize() == dst->getSize() ); 01660 ICLASSERT_RETURN( src->validChannel(srcC) ); 01661 ICLASSERT_RETURN( dst->validChannel(dstC) ); 01662 icl::core::copy<T>(src->getData(srcC),src->getData(srcC)+src->getDim(),dst->getData(dstC)); 01663 } 01664 01665 /* }}} */ 01666 01667 /* {{{ convertChannel */ 01668 01670 01678 template<class S,class D> 01679 inline void convertChannel(const Img<S> *src, int srcC, Img<D> *dst, int dstC){ 01680 FUNCTION_LOG(""); 01681 ICLASSERT_RETURN( src && dst ); 01682 ICLASSERT_RETURN( src->getSize() == dst->getSize() ); 01683 ICLASSERT_RETURN( src->validChannel(srcC) ); 01684 ICLASSERT_RETURN( dst->validChannel(dstC) ); 01685 icl::core::convert<S,D>(src->getData(srcC),src->getData(srcC)+src->getDim(),dst->getData(dstC)); 01686 } 01687 01688 /* }}} */ 01689 01690 /* {{{ clearChannelROI */ 01691 01693 01701 template<class T> 01702 inline void clearChannelROI(Img<T> *im, int c, T clearVal, const utils::Point &offs, 01703 const utils::Size &size) { 01704 FUNCTION_LOG(""); 01705 ICLASSERT_RETURN( im ); 01706 01707 ImgIterator<T> it(im->getData(c),im->getSize().width,utils::Rect(offs,size)); 01708 const ImgIterator<T> itEnd = ImgIterator<T>::create_end_roi_iterator(im->getData(c), 01709 im->getWidth(), 01710 utils::Rect(offs,size)); 01711 std::fill(it,itEnd,clearVal); 01712 } 01713 01715 #ifdef ICL_HAVE_IPP 01716 01717 template <> 01718 inline void clearChannelROI(Img<icl8u> *im, int c, icl8u clearVal, const utils::Point &offs, 01719 const utils::Size &size){ 01720 FUNCTION_LOG(""); 01721 ICLASSERT_RETURN( im ); 01722 ippiSet_8u_C1R(clearVal,im->getROIData(c,offs),im->getLineStep(),size); 01723 } 01725 template <> 01726 inline void clearChannelROI(Img<icl16s> *im, int c, icl16s clearVal, const utils::Point &offs, 01727 const utils::Size &size){ 01728 FUNCTION_LOG(""); 01729 ICLASSERT_RETURN( im ); 01730 ippiSet_16s_C1R(clearVal,im->getROIData(c,offs),im->getLineStep(),size); 01731 } 01733 template <> 01734 inline void clearChannelROI(Img<icl32s> *im, int c, icl32s clearVal, 01735 const utils::Point &offs, const utils::Size &size){ 01736 FUNCTION_LOG(""); 01737 ICLASSERT_RETURN( im ); 01738 ippiSet_32s_C1R(clearVal,im->getROIData(c,offs),im->getLineStep(),size); 01739 } 01741 template <> 01742 inline void clearChannelROI(Img<icl32f> *im, int c, icl32f clearVal, 01743 const utils::Point &offs, const utils::Size &size){ 01744 FUNCTION_LOG(""); 01745 ICLASSERT_RETURN( im ); 01746 ippiSet_32f_C1R(clearVal,im->getROIData(c,offs),im->getLineStep(),size); 01747 } 01748 #endif 01749 01751 /* }}} */ 01752 01754 01755 #define CHECK_VALUES(src,srcC,srcOffs,srcSize,dst,dstC,dstOffs,dstSize) \ 01756 FUNCTION_LOG(""); \ 01757 ICLASSERT_RETURN( src && dst ); \ 01758 ICLASSERT_RETURN( srcSize == dstSize ); \ 01759 ICLASSERT_RETURN( src->validChannel(srcC) ); \ 01760 ICLASSERT_RETURN( dst->validChannel(dstC) ); \ 01761 ICLASSERT_RETURN( srcOffs.x >= 0 && srcOffs.y >= 0 && dstOffs.x >= 0 && dstOffs.y >= 0); \ 01762 ICLASSERT_RETURN( srcOffs.x+srcSize.width <= src->getWidth() && srcOffs.y+srcSize.height <= src->getHeight() ); \ 01763 ICLASSERT_RETURN( dstOffs.x+dstSize.width <= dst->getWidth() && dstOffs.y+dstSize.height <= dst->getHeight() ); 01764 01765 01769 /* {{{ deepCopyChannelROI */ 01770 01772 01782 template <class T> 01783 inline void deepCopyChannelROI(const Img<T> *src, int srcC, const utils::Point &srcOffs, 01784 const utils::Size &srcSize, 01785 Img<T> *dst,int dstC, const utils::Point &dstOffs, 01786 const utils::Size &dstSize) { 01787 CHECK_VALUES(src,srcC,srcOffs,srcSize,dst,dstC,dstOffs,dstSize); 01788 01789 const ImgIterator<T> itSrc(const_cast<T*>(src->getData(srcC)), 01790 src->getSize().width, 01791 utils::Rect(srcOffs,srcSize)); 01792 ImgIterator<T> itDst(dst->getData(dstC),dst->getSize().width,utils::Rect(dstOffs,dstSize)); 01793 const ImgIterator<T> itSrcEnd = ImgIterator<T>::create_end_roi_iterator(src->getData(srcC), 01794 src->getWidth(), 01795 utils::Rect(srcOffs,srcSize)); 01796 01797 for(;itSrc != itSrcEnd;itSrc.incRow(),itDst.incRow()){ 01798 icl::core::copy<T>(&*itSrc,&*itSrc+srcSize.width,&*itDst); 01799 } 01800 } 01801 01802 /* }}} */ 01803 01804 /* {{{ convertChannelROI */ 01805 01808 01822 template <class S,class D> 01823 inline void convertChannelROI(const Img<S> *src, int srcC, const utils::Point &srcOffs, 01824 const utils::Size &srcROISize, 01825 Img<D> *dst,int dstC, const utils::Point &dstOffs, 01826 const utils::Size &dstROISize) 01827 { 01828 FUNCTION_LOG(""); 01829 CHECK_VALUES(src,srcC,srcOffs,srcROISize,dst,dstC,dstOffs,dstROISize); 01830 01831 const ImgIterator<S> itSrc(const_cast<S*>(src->getData(srcC)), 01832 src->getSize().width, 01833 utils::Rect(srcOffs,srcROISize)); 01834 ImgIterator<D> itDst(dst->getData(dstC),dst->getSize().width, 01835 utils::Rect(dstOffs,dstROISize)); 01836 const ImgIterator<S> itSrcEnd = ImgIterator<S>::create_end_roi_iterator(src->getData(srcC), 01837 src->getWidth(), 01838 utils::Rect(srcOffs,srcROISize)); 01839 for(;itSrc != itSrcEnd ;itSrc.incRow(),itDst.incRow()){ 01840 icl::core::convert<S,D>(&*itSrc,&*itSrc+srcROISize.width,&*itDst); 01841 } 01842 } 01843 01845 01846 /* }}} */ 01847 01848 /* {{{ scaledCopyChannelROI */ 01849 01852 01865 template<class T> ICLCore_API 01866 void scaledCopyChannelROI(const Img<T> *src, int srcC, 01867 const utils::Point &srcOffs, 01868 const utils::Size &srcSize, 01869 Img<T> *dst,int dstC, 01870 const utils::Point &dstOffs, 01871 const utils::Size &dstSize, 01872 scalemode eScaleMode); 01873 01874 /* }}} */ 01875 01876 /* {{{ flippedCopyChannelROI */ 01877 01879 01891 template <class T> ICLCore_API 01892 void flippedCopyChannelROI(axis eAxis, 01893 const Img<T> *src,int srcC, const utils::Point &srcOffs, 01894 const utils::Size &srcSize, 01895 Img<T> *dst,int dstC, const utils::Point &dstOffs, 01896 const utils::Size &dstSize); 01897 01898 01900 01914 ICLCore_API void flippedCopy(axis eAxis, const ImgBase *poSrc, ImgBase **ppoDst = 0); 01915 01917 01934 ICLCore_API void flippedCopyROI(axis eAxis, const ImgBase *poSrc, ImgBase **ppoDst = 0); 01935 /* }}} */ 01936 01937 /* }}} */ 01938 } // namespace core 01939 } //namespace icl 01940 01941 #undef CHECK_VALUES 01942