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