#ifndef Img_H #define Img_H #include #include #include #include #include #include namespace icl { /// The Img class implements the ImgBase Image interface with type specific functionalities /** @author Michael Goetting (mgoettin@TechFak.Uni-Bielefeld.de) @author Christof Elbrechter (celbrech@TechFak.Uni-Bielefeld.de) **/ template class Img : public ImgBase { /* this is declare as fried, because it accesses the private append function */ template friend const ImgType* combineImages (const std::vector& vec, ImgBase** ppoDst); /// Private assign operator (internally used) /** This must be kept private! Because the assign operator could otherwise be exploited to violate the Img's const concept (Ask Robert Haschke) **/ Img& shallowCopy(const Img& tSource); /// private append function for a specified image channel /** This must be kept private! Because it could otherwise be exploited to violate the Img's const concept (Ask Robert Haschke) **/ void append(const Img *src, int iChannel=-1); /// private append function for a specified image channel /** This must be kept private! Because it could otherwise be exploited to violate the Img's const concept (Ask Robert Haschke) **/ void append(const Img *src, const std::vector& vChannels); protected: /** @{ @name data **/ /* {{{ open */ /// internally used storage for the image channels std::vector > m_vecChannels; // @} /* }}} */ /** @{ @name auxiliary functions **/ /* {{{ open */ /// Internally creates a new deep copy of a specified Type* /** if the give Type* ptDataToCopy is not NULL, the data addressed from it, is copied deeply into the new created data pointer **/ SmartPtr createChannel(Type *ptDataToCopy=0) const; /// returns the start index for a channel loop /** In some functions to cases must be regarded: - if given channel index is -1, then it has to be iterated over all image channels - else only the given image channel has to be touched To avoid code doublication, one can use the following for-loop
        void foo(int iChannel){
           for(int i = iIndex < 0 ? 0 : iIndex, iEnd = iIndex < 0 ? m_iChannels : iIndex+1; i < iEnd; i++)   { 
                 // do something
           }
        }
        
When using the getIndex functions the loop becomes much more readable:
        void foo(int iChannel){
           for(int i=getStartIndex(iIndex), iEnd=getEndIndex(iIndex); i
        @param iIndex channel index
        @return start index for for-loops
        @see getEndIndex
        **/
    int getStartIndex(int iIndex) const { return iIndex < 0 ? 0 : iIndex; }

    /// returns the end index for a channel loop
    /** this function behaves essentially like the above function 
        @param iIndex channel index
        @return end index for for-loops
        @see getStartIndex
        */
    int getEndIndex(int iIndex) const { return iIndex < 0 ? getChannels() : iIndex+1; }

    // @}

    /* }}} */
          
    /** @{ @name basic image manipulation */
    /* {{{ open */

    /// Scales pixel values from given min/max values to new min/max values (for internal use)
    /** Values exceeding the given range are set to the new min/max values.
        For an automatic scaling use the results of  min(),max() as as arguments.
        (Defining a range allows to compare different images.)
        @param iChannel channel index (if set to -1, then operation is 
        @param srcRange assumption of the images range
        @param dstRange image range after the operation

        performed on all channels)
        **/
    void normalize(int iChannel, const Range &srcRange, const Range &dstRange);

    /// in-place mirror operation on the given image rect (for internal use)
    /** @param eAxis axis for the mirror operation
        @param iChannel channel index to work on
        @param oOffset image rects offset to use
        @param oSize image rects size to use
    **/
    void mirror(axis eAxis, int iChannel,const Point& oOffset, const Size& oSize);

    /* }}} */

    public:
    /** @{ @name constructors / destructor */
    /* {{{ open */

    /// creates a new image specified by the given param struct
    /** @param params initializing image parameters, if null, then a 
        null image is created  
        */
    Img(const ImgParams ¶ms = ImgParams::null);
  
    /// Creates an image with specified number of channels and size.    
    /** the format of the image will be set to "formatMatrix"
        @param size image size
        @param channels Number of Channels 
        **/
    Img(const Size &size, int channels);
 
    /// Creates an image with specified size, number of channels and format
    /** @param s size of the new image
        @param fmt (color)-format of the image
        **/
    Img(const Size &s, format fmt);
 
    /// Crates an image with given size, channel count and format
    /** Note: channel count and format depend on each other, so if
        the given channel count and the given format are not compatible,
        an exception is thrown
        @param s size of the image
        @param channels channel count of the image (must be compatible to fmt)
        @param fmt format of the image (must be compatible to channels)
        */
    Img(const Size &s, int channels, format fmt);
  
    /// Creates an image with specified size and format, using shared data pointers as channel data
    /** The channel count is set to the channel count that is associated with given the format
        @param size new image size
        @param format (color)-format of the image
        @param vptData holds a pointer to channel data pointers. pptData must contain 
        enough Type-pointers for the given format. The data must not be 
        deleted during the "lifetime" of the Img. Call detach after the 
        constructor call, to induce the Img to allocate own memory for 
        the image data.
        **/
    Img(const Size &size, format format, const std::vector& vptData);
  
    /// Creates an image with specified size and channel count, using shared data pointers as channel data
    /** the format is set to formatMatrix
        @param size new image size
        @param channels channel count of the image (format is set to "formatMatrix")
        @param vptData holds a pointer to channel data pointers. pptData must contain 
        enough Type-pointers for the given format. The data must not be 
        deleted during the "lifetime" of the Img. Call detach after the 
        constructor call, to induce the Img to allocate own memory for 
        the image data.
        **/
    Img(const Size &size, int channels, const std::vector& vptData);

    /// Crates an image with given size, channel count and format
    /** Note: channel count and format depend on each other, so if
        the given channel count and the given format are not compatible,
        an exception is thrown
        @param size size of the image
        @param channels channel count of the image (must be compatible to fmt)
        @param fmt format of the image (must be compatible to channels)
        @param vptData array of data pointers, which are used as shared 
        pointers. Ensure, that these pointers are persistent
        during the lifetime of the image, or call detach, to
        make the image allocate it own memory for the data
        */
    Img(const Size &size, int channels, format fmt, const std::vector& vptData);

    /// Copy constructor
    /** Creates a flat copy of the source image. The new image will contain a
        flat copy of all channels of the source image. This constructor is only
        applicable to non-const Img references.  
        @param tSrc non-const reference of source instance
        **/
    Img(const Img& tSrc);
    
    
    
    /// Destructor
    ~Img();
  
    //@}

    /* }}} */
  
    /** @{ @name operators */
    /* {{{ open */
    
    operator Img&(){
      return *this;
    }
    /// Assign operator (flat copy of channels)
    /** Both images will share their channel data. 
        Use deepCopy() to obtain a copy of an image which is not attached to the 
        source image.      
        @param tSource Reference to source object. 
        **/
    Img& operator=(Img& tSource) {
      // call private const-version
      return this->shallowCopy (static_cast&>(tSource));
    }

    /// pixel access operator
    /** This operator may be used, to access the pixel data of the image
        e.g. copy of image data:
        
        Img8u oA(Size(320,240),1),oB(Size(320,240),1);
        for(int x=0;x<320;x++){
        for(int y=0;y<240;y++){
        oB(x,y,0)=oA(x,y,0);
        }
        }
        

Efficiency

Although the ()-operator is compiled inline, and optimized, it is very slow, as it has to select a channel internally (array access) followed by the data access of the selected channel (return array[x+w*y]). A measurement with a "-O3" binary brought the result that pixel access is up to 10 times faster when working directly with a channel data pointer. Nevertheless, the ()-operator is provided in the Img-class, as it offers a very intuitive access to the pixel data. Note: The also provided ImgIterator provides an additional ROI handling mechanism and is more than 5 times faster. @see ImgIterator @see getIterator() @see getROIIterator() @param iX X-Position of the referenced pixel @param iY Y-Position of the referenced pixel @param iChannel channel index **/ Type& operator()(int iX, int iY, int iChannel) { return const_cast(static_cast*>(this)->operator()(iX,iY,iChannel)); } const Type& operator()(int iX, int iY, int iChannel) const { return getData(iChannel)[iX+getWidth()*iY]; } /// sub-pixel access using nearest neighbor interpolation float subPixelNN(float fX, float fY, int iChannel) const { return (*this)((int)fX, (int)fY, iChannel); } /// sub-pixel access using linear interpolation float subPixelLIN(float fX, float fY, int iChannel) const; /// sub-pixel access using region average interpolation float subPixelRA(float fX, float fY, int iChannel) const; /// sub-pixel access operator, uses given interpolation method Type operator()(float fX, float fY, int iChannel, scalemode eMode) const; //@} /* }}} */ /** @{ @name shallow/deepCopy functions */ /* {{{ open */ virtual Img *shallowCopy(const Rect &roi, const std::vector &channelIndices, format fmt, Time=Time::null, ImgBase **ppoDst = NULL); /** Create a shallow copy of an image with given (const version) @see the above function @param roi ROI of the new Image @param channelIndices indices to select from the source image. These channels are shallow-copied into the destination image (if size is null, all channels are selected) @param fmt format of the new image (the channel count that is associated with this format must be equal to the channel count that is implicitely defined by the size of the vector channelIndices @param time new timestamp for the returned image @return shallow-copied image **/ const Img *shallowCopy(const Rect &roi, const std::vector &channelIndices, format fmt, Time time=Time::null) const{ // casting constness away is safe, because we effectively return a const Img* return const_cast*>(this)->shallowCopy(roi,channelIndices,fmt,time,0); } /// Create a shallow copy of this image with a new format /** @param newFmt new format to choose. This must be compatible to the channel count of this image. @param ppoDst destination image (exploited as possible) @return shallow copie with given format of NULL if an error occured **/ Img *reinterpretChannels(format newFmt, Img *poDst = NULL){ ImgBase *poDstBase = poDst; return shallowCopy(getROI(),std::vector(),newFmt,getTime(),&poDstBase); } /// Create a shallow copy of this image with a new format (const version) /** @param newFmt new format to choose. This must be compatible to the channel count of this image. @return shallow copie with given format of NULL if an error occured **/ const Img *reinterpretChannels(format newFmt){ return shallowCopy(getROI(),std::vector(),newFmt,getTime()); } /// Create a shallow copy of the image /** It exploits the given destination image if possible, i.e. if the pixel depth matches. Else this image is released and a new one is created. Optionally a second argument can be specified to get a new image with the given ROI. @param ppoDst pointer to the destination image pointer If ppoDst is NULL, a new image is created, if ppoDst points to NULL, a new image is created at *ppoDst; @param roi new ROI of the new image. If Rect::null, the source images roi is used. @return shallow copy of this image **/ Img* shallowCopy(const Rect &roi,Img* poDst = NULL){ ImgBase *poDstBase = poDst; return shallowCopy(roi,std::vector(),getFormat(),getTime(),&poDstBase); } /// Create a shallow copy of a const source image /** In contrast to the not const function shallowCopy, the const one does not provide to specify a destination image pointer, because this must neither be const nor not const. If it would be const, it would not be possible to adapt it to correct parameters, otherwise it would violate the const concept as it could be used to change the const result.\n This function can only be used to get const copy of a source image with a special ROI. @param roi ROI of the returned image (Rect::null is not allowed!) @return shallow copy of this image with specified ROI */ const Img* shallowCopy(const Rect& roi) const { // casting constness away is safe, because we effectively return a const Img* return const_cast*>(this)->shallowCopy(roi,0); } /// Create a shallow copy of selected channels of an image /** This function can be used if only one or some channels of a given const image should be used in further processing steps. It helps to avoid the necessity of "deepCopy" calls there. @param channelIndices vector containing channel indices to copy @param ppoDst destination image (if Null, a new one is created) @return image containing only the selected channels (as shallow copies) format of that image becomes formatMatrix @see shallowCopy */ Img* selectChannels (const std::vector& channelIndices, Img* poDst=0){ ImgBase *poDstBase = poDst; return shallowCopy(getROI(),channelIndices,formatMatrix,getTime(),&poDstBase); } /// Create a shallow copy of a single image channel of an image /** This function is a shortcut to use icl::ImgBase::selectChannels(const std::vector&,icl::ImgBase**) to select a single channel from an image @param channelIndex index of the channel to select (if invalid, NULL is returned) @param ppoDst destination image @return image containing only the selected channel **/ Img *selectChannel(int channelIndex, Img *poDst=0){ ICLASSERT_RETURN_VAL(validChannel(channelIndex), 0); std::vector v(1); v[0]= channelIndex; return selectChannels(v,poDst); } /// Create a shallow copy of selected channels of a const image. /** @param channelIndices vector containing channel indices to copy @return const image containing only the selected channels */ const Img* selectChannels (const std::vector& channelIndices) const { // casting constness away is safe, because we effectively return a const Img* return const_cast*>(this)->selectChannels(channelIndices, 0); } /// Create a shallow copy of a single image channel of a const image /** This function is a shortcut to use icl::ImgBase::selectChannels(const std::vector&)const to select a single channel from a const image image @param channelIndex index of the channel to select (if invalid, NULL is returned) @return const image containing only the selected channel **/ const ImgBase *selectChannel(int channelIndex) const{ ICLASSERT_RETURN_VAL(validChannel(channelIndex), 0); std::vector v(1); v[0]= channelIndex; return selectChannels(v); } //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ //------------------------------------------------------------------------------ /// Perform a deep copy of an image /** \copydoc icl::ImgBase::deepCopy(icl::ImgBase**)const */ virtual Img* deepCopy(ImgBase** ppoDst=0) const; /// Perform a deep copy of an image /** This is an overloaded version of the above function. It behaves essentially like the above function, except getting an Img* as destination image argument, what allows to apply the operation without a depth switch. @param poDst destination image, if NULL, a new Img is created @return deep copy of this image **/ Img *deepCopy(Img *poDst) const; /// Perform a deep copy of an images ROI /** \copydoc icl::ImgBase::deepCopyROI(icl::ImgBase**)const */ virtual Img *deepCopyROI(ImgBase **ppoDst=0) const; /// Perform a deep copy of an images ROI /** This is an overloaded version of the above function. It behaves essentially like the above function, except getting an Img* as destination image argument, what allows to apply the operation without a depth switch. @param poDst destination image, if NULL, a new Img is created @return deep copy of this images ROI **/ Img *deepCopyROI(Img *poDst) const; //@} /* }}} */ /** @{ scaled-, and flipped-Copy functions */ /* {{{ open */ /// create a scaled copy of this image /** \copydoc icl::ImgBase::scaledCopy(const icl::Size&,icl::scalemode)const */ virtual Img *scaledCopy(const Size &newSize, scalemode eScaleMode=interpolateNN) const; /// create a scaled copy of this image /** \copydoc icl::ImgBase::scaledCopy(icl::ImgBase**,icl::scalemode)const */ virtual Img *scaledCopy(ImgBase **ppoDst=0, scalemode eScaleMode=interpolateNN) const; /// create a scaled copy of this image /** Overloaded function to create a scaled copy of an image. This function gets an Img* as destination, what allows to apply the operation without any depth-switch. @param poDst destination image pointer, if NULL, a new Img is created @param eScaleMode interpolation method to use when scaling */ Img *scaledCopy(Img *poDst, scalemode eScaleMode=interpolateNN) const; /// create a scaled copy of an images ROI with given size /** \copydoc icl::ImgBase::scaledCopyROI(const icl::Size&,icl::scalemode)const */ virtual Img *scaledCopyROI(const Size &newSize, scalemode eScaleMode=interpolateNN) const; /// create a scaled copy of an images ROI with given destination image /** \copydoc icl::ImgBase::scaledCopyROI(icl::ImgBase**,icl::scalemode)const*/ virtual Img *scaledCopyROI(ImgBase **ppoDst=0, scalemode eScaleMode=interpolateNN) const; /// create a scaled copy of this images ROI /** Overloaded function to create a scaled copy of an images ROI. This function gets an Img* as destination, what allows to apply the operation without any depth-switch. @param poDst destination image pointer, if NULL, a new Img is created @param eScaleMode interpolation method to use when scaling */ Img *scaledCopyROI(Img *poDst, scalemode eScaleMode=interpolateNN) const; //@} /* }}} */ /** @{ @name organization and channel management */ /* {{{ open */ /// Makes the image channels inside the Img independent from other Img. /** \copydoc icl::ImgBase::detach(int) */ virtual void detach(int iIndex = -1); /// Removes a specified channel. /** \copydoc icl::ImgBase::removeChannel(int) */ virtual void removeChannel(int iChannel); /// Append channels of external Img to the existing Img. /** Both objects will share their data (cheap copy). If a non-matrix format image gets new channels using it's append method, the new channel count will not match to the channel count, that is associated with the current format. In this case, a waring is written to std::out, and the format will be set to formatMatrix implicitly. @param src source image @param iChannel channel to append (or all, if < 0) **/ void append(Img *src, int iChannel=-1) { // call private const-version this->append (static_cast*>(src), iChannel); } /// Append a set of selected channels from source image /** @param src source image @param vChannels vector of channels indices*/ void append(Img *src, const std::vector& vChannels) { // call private const-version this->append (static_cast*>(src), vChannels); } /// Swap channel A and B /** \copydoc icl::ImgBase::swapChannels(int,int) */ virtual void swapChannels(int iIndexA, int iIndexB); /// Replace the channel A of this image with the channel B another image. /** Both images must have the same width and height. @param iThisIndex channel to replace @param iOtherIndex channel to replace with @param poOtherImg Image that contains the new channel **/ void replaceChannel(int iThisIndex, Img *poOtherImg, int iOtherIndex); /// sets the channel count to a new value /** \copydoc icl::ImgBase::setChannels(int) */ virtual void setChannels(int iNewNumChannels); /// resizes the image to new values /** \copydoc icl::ImgBase::setSize(const icl::Size&) */ virtual void setSize(const Size &s); //@} /* }}} */ /** @{ @name getter functions */ /* {{{ open */ /// Returns max pixel value of channel iChannel within ROI /** @param iChannel Index of channel **/ Type getMax(int iChannel) const; /// Returns min pixel value of channel iChannel within ROI /** @param iChannel Index of channel **/ Type getMin(int iChannel) const; /// return maximal pixel value over all channels (restricted to ROI) Type getMin() const; /// return minimal pixel value over all channels (restricted to ROI) Type getMax() const; /// Returns min and max pixel values of channel iChannel within ROI /** @param iChannel Index of channel **/ const Range getMinMax(int iChannel) const; /// return minimal and maximal pixel values over all channels (restricted to ROI) const Range getMinMax() const; /// Returns the width of an image line in bytes /** \copydoc icl::ImgBase::getLineStep()const **/ virtual int getLineStep() const{ return getSize().width*sizeof(Type); } /// returns a Type save data data pointer to the channel data origin /** If the channel index is not valid (<0 or >= getChannels) NULL is returned and an error is written to std::err @param iChannel specifies the channel @return data origin pointer to the specified channel */ Type* getData(int iChannel) { return const_cast(static_cast*>(this)->getData(iChannel)); } /// returns a Type save data data pointer to the channel data origin (const) /** \copydoc getData(int)*/ const Type* getData(int iChannel) const { FUNCTION_LOG(""); ICLASSERT_RETURN_VAL(validChannel(iChannel), 0); return m_vecChannels[iChannel].get(); } /// returns a Type save data pointer to the first pixel within the images roi /** The following ASCII image shows an images ROI.
                       1st roi-pixel
                            |
                        ....|....................         ---
                        ....|..ooooooooo......... ---      |
                        ....|..ooooooooo.........  |       |
                        ....|..ooooooooo......... roi-h  image-h
        1st image pixel ....|..ooooooooo.........  |       |
             |          ....+->xoooooooo......... ---      |
             +--------->x........................         ---
                               |-roi-w-|
                        |---------image-w-------|
  
        
Note: most ipp-function require the ROI-data pointer @param iChannel specifies the channel @return roi data pointer **/ Type* getROIData(int iChannel) { return const_cast(static_cast*>(this)->getROIData(iChannel)); } /// returns a Type save data pointer to the first pixel within the images roi (const) /** \copydoc getROIData(int) */ const Type* getROIData(int iChannel) const { FUNCTION_LOG(""); ICLASSERT_RETURN_VAL(validChannel(iChannel),0); return getData(iChannel) + m_oParams.getPixelOffset(); } /// returns the data pointer to a pixel with defined offset /** In some functions like filters, it might be necessary to change the images ROI parameters before applying the underlying image operation. Temporarily changing the images ROI parameters causes problems in multi-threaded environments. To avoid this, this function provides access to a data pointer to an arbitrary notional ROI-offset @param iChannel selects the channel @param p notional ROI offset @return data pointer with notional ROI offset p **/ Type* getROIData(int iChannel, const Point &p) { return const_cast(static_cast*>(this)->getROIData(iChannel, p)); } /// returns the data pointer to a pixel with defined offset (const) /** \copydoc getROIData(int,const icl::Point&) */ const Type* getROIData(int iChannel, const Point &p) const { FUNCTION_LOG(""); ICLASSERT_RETURN_VAL(validChannel(iChannel),0); return getData(iChannel) + p.x + (p.y * getWidth()); } /// returns the raw- data pointer of an image channel /** \copydoc icl::ImgBase::getDataPtr(int) **/ virtual void* getDataPtr(int iChannel){ return getData(iChannel); } /// returns the raw- data pointer of an image channel (const) /** \copydoc icl::ImgBase::getDataPtr(int)const **/ virtual const void* getDataPtr(int iChannel) const{ return getData(iChannel); } //@} /* }}} */ /** @{ @name basic in-place image manipulations (scale mirror,clear and normalize) */ /* {{{ open */ /// perform an in-place resize of the image (keeping the data) /** \copydoc icl::ImgBase::scale(const icl::Size&,icl::scalemode)*/ virtual void scale(const Size &s, scalemode eScaleMode=interpolateNN); /// perform an in-place mirror operation on the image /** \copydoc icl::ImgBase::mirror(icl::axis,bool) */ virtual void mirror(axis eAxis, bool bOnlyROI=false); /// Sets the ROI pixels of one or all channels to a specified value /** @param iChannel Channel to fill with zero (default: -1 = all channels) @param tValue destination value (default: 0) @param bROIOnly if set false, the whole image is set to tValue **/ void clear(int iChannel = -1, Type tValue = 0, bool bROIOnly=true); /// Normalize the channel min/ max range to the new min, max range. /** The min/ max range from the source channels are automatically detected, separately for each channel. @param dstRange new image range **/ void normalizeAllChannels(const Range &dstRange); /// Normalize the channel from a given min/max range to the new range /** @param iChannel channel index @param srcRange notional image range befor this function call @param dstRange image range after this function call **/ void normalizeChannel(int iChannel, const Range &srcRange, const Range &dstRange); /// Normalize the channel from a given min/max range to the new range /** The min/ max range from the source channel is automatically detected, separately for this channel @param iChannel channel index @param dstRange destination image range **/ void normalizeChannel(int iChannel,const Range &dstRange); /// Normalize the image from a given min/max range to the new range /** @param srcRange notional image range befor this function call @param dstRange image range after this function call **/ void normalizeImg(const Range &srcRange, const Range &dstRange); /// Normalize the image from a min/max range to the new range /** The min/ max range from the image is automatically detected, combined over all image channels. @param dstRange destination image range **/ void normalizeImg(const Range &dstRange); //@} /* }}} */ /** @{ @name pixel access using roi iterator */ /* {{{ open */ /// type definition for ROI iterator typedef ImgIterator iterator; /// type definition for a const ROI iterator typedef ConstImgIterator const_iterator; /// returns the iterator for the hole image /** The following example taken from ImgIterator.h will show the iterator usage: \code void channel_convolution_3x3(Img32f &src, Img32f &dst,icl32f *pfMask, int iChannel){ for(Img32f::iterator s=src.getIterator(iChannel) d=dst.getIterator(iChannel) ; s.inRegion() ; s++,d++){ icl32f *m = pfMask; (*d) = 0; for(Img32f::iterator sR(s, 3, 3); sR.inRegion(); sR++,m++){ (*d) += (*sR) * (*m); } } } \endcode Note: The performance hints illustrated in the ImgIterator documentation. @param iChannel selected channel index @return iterator @see ImgIterator @see end **/ inline iterator getIterator(int iChannel) { FUNCTION_LOG("begin(" << iChannel << ")"); ICLASSERT_RETURN_VAL(validChannel(iChannel), iterator()); return iterator(getData(iChannel),getWidth(),Rect(Point::null,getSize())); } /// returns an iterator to an images ROI pixels /** this function behaves essentially like the above function @param iChannel selects a channel @return roi-iterator @see getIterator */ inline iterator getROIIterator(int iChannel) { FUNCTION_LOG("begin(" << iChannel << ")"); ICLASSERT_RETURN_VAL(validChannel(iChannel), iterator()); return iterator(getData(iChannel),getWidth(),getROI()); } /// const version of getIterator inline const_iterator getIterator(int iChannel) const { FUNCTION_LOG("begin(" << iChannel << ")"); ICLASSERT_RETURN_VAL(validChannel(iChannel), const_iterator()); return const_iterator(getData(iChannel),getWidth(),Rect(Point::null,getSize())); } /// const version of getROIIterator inline const_iterator getROIIterator(int iChannel) const { FUNCTION_LOG("begin(" << iChannel << ")"); ICLASSERT_RETURN_VAL(validChannel(iChannel), const_iterator()); return const_iterator(getData(iChannel),getWidth(),getROI()); } //@} /* }}} */ };// class Img /* {{{ global functions */ /// Combine several images using shallow copy. template const ImgType* combineImages (const std::vector& vec); /// Combine several images using shallow copy. Non-const version template ImgType* combineImages (const std::vector& vec) { return const_cast(combineImages(reinterpret_cast&>(vec))); } /* {{{ deepCopyChannel */ template inline void deepCopyChannel( const Img *src, int srcC, Img *dst, int dstC){ FUNCTION_LOG(""); ICLASSERT_RETURN( src && dst ); ICLASSERT_RETURN( src->getSize() == dst->getSize() ); ICLASSERT_RETURN( src->validChannel(srcC) ); ICLASSERT_RETURN( dst->validChannel(dstC) ); icl::copy(src->getData(srcC),src->getData(srcC)+src->getDim(),dst->getData(dstC)); } /* }}} */ /* {{{ convertChannel */ /// copies/converts the data from one image to another image (IPP-OPTIMIZED) /** The deepCopyChannel function is a higher lever wrapper for the icl::copy(..) function. It extracts the data pointers and data dimension from the source- and destination image to call icl::copy(..) @param src source image @param srcC source images channel @param dst destination image @param dstC destination image channel **/ template inline void convertChannel(const Img *src, int srcC, Img *dst, int dstC){ FUNCTION_LOG(""); ICLASSERT_RETURN( src && dst ); ICLASSERT_RETURN( src->getSize() == dst->getSize() ); ICLASSERT_RETURN( src->validChannel(srcC) ); ICLASSERT_RETURN( dst->validChannel(dstC) ); icl::convert(src->getData(srcC),src->getData(srcC)+src->getDim(),dst->getData(dstC)); } /* }}} */ /* {{{ clearChannelROI */ /// sets an arbitrary image ROI to a given value /** This function is used as basic operation for higher level image operation like Img::clear(T value). @param im image @param c channel @param clearVal value for the cleared pixels @param offs lower left point for the to-be-cleared region @param size size of the to-be-cleared region */ template inline void clearChannelROI(Img *im, int c, T clearVal, const Point &offs, const Size &size) { FUNCTION_LOG(""); ICLASSERT_RETURN( im ); for(ImgIterator it(im->getData(c),im->getSize().width,Rect(offs,size)); it.inRegion(); ++it) { *it = clearVal; } } /** \cond */ #ifdef WITH_IPP_OPTIMIZATION /// IPP-OPTIMIZED specialization for icl8u clearing (using ippiSet) template <> inline void clearChannelROI(Img *im, int c, icl8u clearVal, const Point &offs, const Size &size){ FUNCTION_LOG(""); ICLASSERT_RETURN( im ); ippiSet_8u_C1R(clearVal,im->getROIData(c,offs),im->getLineStep(),size); } /// IPP-OPTIMIZED specialization for icl16s clearing (using ippiSet) template <> inline void clearChannelROI(Img *im, int c, icl16s clearVal, const Point &offs, const Size &size){ FUNCTION_LOG(""); ICLASSERT_RETURN( im ); ippiSet_16s_C1R(clearVal,im->getROIData(c,offs),im->getLineStep(),size); } /// IPP-OPTIMIZED specialization for icl32s clearing (using ippiSet) template <> inline void clearChannelROI(Img *im, int c, icl32s clearVal, const Point &offs, const Size &size){ FUNCTION_LOG(""); ICLASSERT_RETURN( im ); ippiSet_32s_C1R(clearVal,im->getROIData(c,offs),im->getLineStep(),size); } /// IPP-OPTIMIZED specialization for icl32f clearing (using ippiSet) template <> inline void clearChannelROI(Img *im, int c, icl32f clearVal, const Point &offs, const Size &size){ FUNCTION_LOG(""); ICLASSERT_RETURN( im ); ippiSet_32f_C1R(clearVal,im->getROIData(c,offs),im->getLineStep(),size); } #endif /** \endcond */ /* }}} */ /* {{{ deepCopyChannelROI */ /// copies the channel roi from one image to another /** Essential deep copy function. @param src source image @param srcC source channel @param srcOffs source images ROI offset @param srcSize source images ROI size @param dst destination image @param dstC destination channel @param dstOffs destination images ROI offset @param dstSize destination images ROI size (must be equal to srcSize) **/ template inline void deepCopyChannelROI(const Img *src,int srcC, const Point &srcOffs, const Size &srcSize, Img *dst,int dstC, const Point &dstOffs, const Size &dstSize) { FUNCTION_LOG(""); ICLASSERT_RETURN( src && dst ); ICLASSERT_RETURN( srcSize == dstSize ); ICLASSERT_RETURN( src->validChannel(srcC) ); ICLASSERT_RETURN( dst->validChannel(dstC) ); ICLASSERT_RETURN( srcOffs.x >= 0 && srcOffs.y >= 0 && dstOffs.x >= 0 && dstOffs.y >= 0); ICLASSERT_RETURN( srcOffs.x+srcSize.width <= src->getWidth() && srcOffs.y+srcSize.height <= src->getHeight() ); ICLASSERT_RETURN( dstOffs.x+dstSize.width <= dst->getWidth() && dstOffs.y+dstSize.height <= dst->getHeight() ); ConstImgIterator itSrc(src->getData(srcC),src->getSize().width,Rect(srcOffs,srcSize)); ImgIterator itDst(dst->getData(dstC),dst->getSize().width,Rect(dstOffs,dstSize)); for(;itSrc.inRegion();itSrc.incRow(),itDst.incRow()){ icl::copy(&*itSrc,&*itSrc+srcSize.width,&*itDst); } } /* }}} */ /* {{{ convertChannelROI */ //@{ @name type conversion of channel ROIs /// copies/converts the ROI data from one image to the ROI of another image (IPP-OPTIMIZED) /** This function is used by all other deepCopyROI functions internally. It copies / converts ROI image data to another images ROI using the icl::copy(..) function line by line or, in case of IPP-optimization enabled, corresponding ippCopy/ippConvert Calls (see the following specialized template functions also). @param src source image @param srcC source image channel @param srcOffs source images ROI-offset (src->getROIOffset() is not regarded) @param srcSize source images ROI-size (src->getROISize() is not regarded) @param dst destination image @param dstC destination image channel @param dstOffs destination images ROI-offset (dst->getROIOffset() is not regarded) @param dstSize destination images ROI-size (dst->getROISize() is not regarded) @param dstSize destination images ROI-size (dst->getROISize() is not regarded) **/ template inline void convertChannelROI(const Img *src,int srcC, const Point &srcOffs, const Size &srcSize, Img *dst,int dstC, const Point &dstOffs, const Size &dstSize) { FUNCTION_LOG(""); ICLASSERT_RETURN( src && dst ); ICLASSERT_RETURN( srcSize == dstSize ); ICLASSERT_RETURN( src->validChannel(srcC) ); ICLASSERT_RETURN( dst->validChannel(dstC) ); ICLASSERT_RETURN( srcOffs.x >= 0 && srcOffs.y >= 0 && dstOffs.x >= 0 && dstOffs.y >= 0); ICLASSERT_RETURN( srcOffs.x+srcSize.width <= src->getWidth() && srcOffs.y+srcSize.height <= src->getHeight() ); ICLASSERT_RETURN( dstOffs.x+dstSize.width <= dst->getWidth() && dstOffs.y+dstSize.height <= dst->getHeight() ); ConstImgIterator itSrc(src->getData(srcC),src->getSize().width,Rect(srcOffs,srcSize)); ImgIterator itDst(dst->getData(dstC),dst->getSize().width,Rect(dstOffs,dstSize)); for(;itSrc.inRegion();itSrc.incRow(),itDst.incRow()){ icl::convert(&*itSrc,&*itSrc+srcSize.width,&*itDst); } } //@} /* }}} */ /* {{{ scaledCopyChannelROI */ //@{ @name scaling of channel ROIs /// scales an image channels ROI into another images ROI (with implicit type conversion) (IPP-OPTIMIZED) /** This function provides all necessary functionalities for scaling images. Please regard, that the fallback- implementation is very slow. Only scaling operations with identical source and destination type is optimized by corresponding ippResize calls (see also the specialized template functions). @param src source image @param srcC source image channel @param srcOffs source images ROI-offset (src->getROIOffset() is not regarded) @param srcSize source images ROI-size (src->getROISize() is not regarded) @param dst destination image @param dstC destination image channel @param dstOffs destination images ROI-offset (dst->getROIOffset() is not regarded) @param dstSize destination images ROI-size (dst->getROISize() is not regarded) @param eScaleMode scaling mode to use (nearest neighbor, linear, or region-average) **/ template void scaledCopyChannelROI(const Img *src,int srcC, const Point &srcOffs, const Size &srcSize, Img *dst,int dstC, const Point &dstOffs, const Size &dstSize, scalemode eScaleMode); /* }}} */ /* {{{ flippedCopyChannelROI */ /// mirror copy ROI data from one image to the ROI of another image (IPP-OPTIMIZED) /** This function is used by flippedCopyROI and Mirror operator. @param eAxis mirror axis (axisHorz, axisVert or axisBoth) @param src source image @param srcC source image channel @param srcOffs source images ROI-offset (src->getROIOffset() is not regarded) @param srcSize source images ROI-size (src->getROISize() is not regarded) @param dst destination image @param dstC destination image channel @param dstOffs destination images ROI-offset (dst->getROIOffset() is not regarded) @param dstSize destination images ROI-size (dst->getROISize() is not regarded) @param dstSize destination images ROI-size (dst->getROISize() is not regarded) **/ template void flippedCopyChannelROI(axis eAxis, const Img *src,int srcC, const Point &srcOffs, const Size &srcSize, Img *dst,int dstC, const Point &dstOffs, const Size &dstSize); /// mirror copy of an image from source to destination image (1:1 copy) /** This function creates a flipped instance of this image. Even the ROI is flipped internally. Example:
        ......                    ......     r = roi
        ..rrrr  -> flipped x ->   rrrr..
        ..rrrr                    rrrr..
      
@param eAxis axis to flip @param poSrc source image @param ppoDst image. This image is exploited if possible. It is adjusted to the source image in depth, size,channels,format,and time **/ void flippedCopy(axis eAxis, const ImgBase *poSrc, ImgBase **ppoDst=0); /// mirror copy of an images ROI into a destination images ROI /** Example:
        ......                    ......    R,r = roi
        ..RRrr  -> flipped x ->   rrRR..
        ..RRrr                    rrRR..
      
@param eAxis axis to flip @param poSrc source image @param ppoDst destination image (expoited if possible). This images ROI size must be equal to ppoDst's ROI size otherwise an errormessage is shown, and the function returns 0. If ppoDst is null, a new image is created with size of this images ROI size. If ppoDst points to NULL, the new image is created at *ppoDst. @return flippedCopy **/ void flippedCopyROI(axis eAxis, const ImgBase *poSrc, ImgBase **ppoDst=0); /* }}} */ /* }}} */ } //namespace icl #endif //Img_H