# Cinder

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

# include/cinder/Channel.h

Go to the documentation of this file.

    00001 /*
    00002  Copyright (c) 2010, The Barbarian Group
    00003  All rights reserved.
    00004
    00005  Redistribution and use in source and binary forms, with or without modification, are permitted provided that
    00006  the following conditions are met:
    00007
    00008     * Redistributions of source code must retain the above copyright notice, this list of conditions and
    00009     the following disclaimer.
    00010     * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and
    00011     the following disclaimer in the documentation and/or other materials provided with the distribution.
    00012
    00013  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
    00014  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
    00015  PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
    00016  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
    00017  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    00018  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    00019  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    00020  POSSIBILITY OF SUCH DAMAGE.
    00021 */
    00022
    00023 #pragma once
    00024
    00025 #include "cinder/Cinder.h"
    00026 #include "cinder/Area.h"
    00027
    00028 namespace cinder {
    00029
    00030 typedef shared_ptr<class ImageSource> ImageSourceRef;
    00031
    00032 template<typename T>
    00033 class ChannelT {
    00034  protected:
    00035     struct Obj {
    00036         Obj( int32_t width, int32_t height );
    00037         Obj( int32_t aWidth, int32_t aHeight, int32_t aRowBytes, uint8_t aIncrement, bool aOwnsData, T *aData );
    00038         ~Obj();
    00039
    00040         int32_t                     mWidth, mHeight, mRowBytes;
    00041         T                           *mData;
    00042         uint8_t                     mIncrement;
    00043         bool                        mOwnsData;
    00044
    00045         void                        (*mDeallocatorFunc)(void *refcon);
    00046         void                        *mDeallocatorRefcon;
    00047     };
    00048
    00049  public:
    00051     ChannelT() {}
    00053     ChannelT( int32_t width, int32_t height );
    00055     ChannelT( int32_t width, int32_t height, int32_t rowBytes, uint8_t increment, T *data );
    00057     ChannelT( ImageSourceRef imageSource );
    00058
    00059     operator ImageSourceRef() const;
    00060
    00062     ChannelT            clone( bool copyPixels = true ) const;
    00064     ChannelT            clone( const Area &area, bool copyPixels = true ) const;
    00065
    00067     int32_t     getWidth() const { return mObj->mWidth; }
    00069     int32_t     getHeight() const { return mObj->mHeight; }
    00071     Vec2i       getSize() const { return Vec2i( mObj->mWidth, mObj->mHeight ); }
    00073     float       getAspectRatio() const { return mObj->mWidth / (float)mObj->mHeight; }
    00075     Area        getBounds() const { return Area( 0, 0, mObj->mWidth, mObj->mHeight ); }
    00077     int32_t     getRowBytes() const { return mObj->mRowBytes; }
    00079     uint8_t     getIncrement() const { return mObj->mIncrement; }
    00081     bool        isPlanar() const { return mObj->mIncrement == 1; }
    00082
    00083     T*          getData() { return mObj->mData; }
    00084     const T*    getData() const { return mObj->mData; }
    00085     T*          getData( const Vec2i &offset ) { return reinterpret_cast<T*>( reinterpret_cast<unsigned char*>( mObj->mData + offset.x * mObj->mIncrement ) + offset.y * mObj->mRowBytes ); }
    00086     const T*    getData( const Vec2i &offset ) const { return reinterpret_cast<T*>( reinterpret_cast<unsigned char*>( mObj->mData + offset.x * mObj->mIncrement ) + offset.y * mObj->mRowBytes ); }
    00087     T*          getData( int32_t x, int32_t y ) { return reinterpret_cast<T*>( reinterpret_cast<unsigned char*>( mObj->mData + x * mObj->mIncrement ) + y * mObj->mRowBytes ); }
    00088     const T*    getData( int32_t x, int32_t y ) const { return reinterpret_cast<T*>( reinterpret_cast<unsigned char*>( mObj->mData + x * mObj->mIncrement ) + y * mObj->mRowBytes ); }
    00089
    00091     T       getValue ( Vec2i pos ) const { pos.x = constrain<int32_t>( pos.x, 0, mObj->mWidth - 1); pos.y = constrain<int32_t>( pos.y, 0, mObj->mHeight - 1 ); return *getData( pos ); }
    00093     void    setValue( Vec2i pos, T v ) { pos.x = constrain<int32_t>( pos.x, 0, mObj->mWidth - 1); pos.y = constrain<int32_t>( pos.y, 0, mObj->mHeight - 1 ); *getData( pos ) = v; }
    00094
    00095     void        copyFrom( const ChannelT<T> &srcChannel, const Area &srcArea, const Vec2i &relativeOffset = Vec2i::zero() );
    00096
    00097     T           areaAverage( const Area &area ) const;
    00098
    00099     void        setDeallocator( void(*aDeallocatorFunc)( void * ), void *aDeallocatorRefcon );
    00100
    00102
    00103     typedef typename shared_ptr<Obj>::unspecified_bool_type unspecified_bool_type;
    00104     operator unspecified_bool_type() const { return static_cast<typename shared_ptr<Obj>::unspecified_bool_type>( mObj ); }
    00105     void reset() { mObj.reset(); }
    00107
    00108     class Iter {
    00109      public:
    00110         Iter( ChannelT<T> &channelT, const Area &area )
    00111             : mInc( channelT.getIncrement() ), mRowInc( channelT.getRowBytes() )
    00112         {
    00113             Area clippedArea( area.getClipBy( channelT.getBounds() ) );
    00114             mWidth = clippedArea.getWidth();
    00115             mHeight = clippedArea.getHeight();
    00116             mLinePtr = reinterpret_cast<uint8_t*>( channelT.getData( clippedArea.getUL() ) );
    00117             mPtr = reinterpret_cast<T*>( mLinePtr );
    00118             mStartX = mX = clippedArea.getX1();
    00119             mStartY = mY = clippedArea.getY1();
    00120             mEndX = clippedArea.getX2();
    00121             mEndY = clippedArea.getY2();
    00122             // in order to be at the right place after an initial call to line(), we need to back up one line
    00123             mY = clippedArea.getY1() - 1;
    00124             mLinePtr -= mRowInc;
    00125         }
    00126
    00127         T&          v() const { return *mPtr; }
    00128         T&          v( int32_t xOff, int32_t yOff ) const { return mPtr[xOff * mInc + yOff * mRowInc]; }
    00129         T&          vClamped ( int32_t xOff, int32_t yOff ) const
    00130                         {   xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
    00131                             return mPtr[xOff * mInc + yOff * mRowInc]; }
    00132
    00133         const int32_t   x() const { return mX; }
    00134         const int32_t   y() const { return mY; }
    00135         Vec2i           getPos() const { return Vec2i( mX, mY ); }
    00136
    00137         bool pixel() {
    00138             ++mX;
    00139             mPtr += mInc;
    00140             return mX < mEndX;
    00141         }
    00142
    00143         bool line() {
    00144             ++mY;
    00145             mLinePtr += mRowInc;
    00146             mPtr = reinterpret_cast<T*>( mLinePtr );
    00147             // in order to be at the right place after an initial call to pixel(), we need to back up one pixel
    00148             mPtr -= mInc;
    00149             mX = mStartX - 1;
    00150             return mY < mEndY;
    00151         }
    00152
    00153         int32_t     getWidth() { return mWidth; }
    00154         int32_t     getHeight() { return mHeight; }
    00155
    00156         uint8_t             mInc;
    00157         uint8_t             *mLinePtr;
    00158         T                   *mPtr;
    00159         int32_t             mRowInc, mWidth, mHeight;
    00160         int32_t             mX, mY, mStartX, mStartY, mEndX, mEndY;
    00161     };
    00162
    00163     class ConstIter {
    00164      public:
    00165         ConstIter( const ChannelT<T> &channelT, const Area &area )
    00166             : mInc( channelT.getIncrement() ), mRowInc( channelT.getRowBytes() )
    00167         {
    00168             Area clippedArea( area.getClipBy( channelT.getBounds() ) );
    00169             mWidth = clippedArea.getWidth();
    00170             mHeight = clippedArea.getHeight();
    00171             mLinePtr = reinterpret_cast<const uint8_t*>( channelT.getData( clippedArea.getUL() ) );
    00172             mPtr = reinterpret_cast<const T*>( mLinePtr );
    00173             mStartX = mX = clippedArea.getX1();
    00174             mStartY = mY = clippedArea.getY1();
    00175             mEndX = clippedArea.getX2();
    00176             mEndY = clippedArea.getY2();
    00177             // in order to be at the right place after an initial call to line(), we need to back up one line
    00178             mY = clippedArea.getY1() - 1;
    00179             mLinePtr -= mRowInc;
    00180         }
    00181
    00182         const T&    v() const { return *mPtr; }
    00183         const T&    v( int32_t xOff, int32_t yOff ) const { return mPtr[xOff * mInc + yOff * mRowInc]; }
    00184         const T&    vClamped( int32_t xOff, int32_t yOff ) const
    00185                         {   xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
    00186                             return mPtr[xOff * mInc + yOff * mRowInc]; }
    00187
    00188         const int32_t   x() const { return mX; }
    00189         const int32_t   y() const { return mY; }
    00190         Vec2i           getPos() const { return Vec2i( mX, mY ); }
    00191
    00192         bool pixel() {
    00193             ++mX;
    00194             mPtr += mInc;
    00195             return mX < mEndX;
    00196         }
    00197
    00198         bool line() {
    00199             ++mY;
    00200             mLinePtr += mRowInc;
    00201             mPtr = reinterpret_cast<const T*>( mLinePtr );
    00202             // in order to be at the right place after an initial call to pixel(), we need to back up one pixel
    00203             mPtr -= mInc;
    00204             mX = mStartX - 1;
    00205             return mY < mEndY;
    00206         }
    00207
    00208         int32_t     getWidth() { return mWidth; }
    00209         int32_t     getHeight() { return mHeight; }
    00210
    00211         uint8_t             mInc;
    00212         const uint8_t       *mLinePtr;
    00213         const T             *mPtr;
    00214         int32_t             mRowInc, mWidth, mHeight;
    00215         int32_t             mX, mY, mStartX, mStartY, mEndX, mEndY;
    00216     };
    00217
    00218     Iter        getIter() { return Iter( *this, this->getBounds() ); }
    00219     Iter        getIter( const Area &area ) { return Iter( *this, area ); }
    00220     ConstIter   getIter() const { return ConstIter( *this, this->getBounds() ); }
    00221     ConstIter   getIter( const Area &area ) const { return ConstIter( *this, area ); }
    00222
    00223  protected:
    00224     shared_ptr<Obj>     mObj;
    00225 };
    00226
    00227
    00228 typedef ChannelT<uint8_t>   Channel;
    00229 typedef ChannelT<uint8_t>   Channel8u;
    00230 typedef ChannelT<float>     Channel32f;
    00231
    00232 } // namespace cinder