00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
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
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
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
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
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 }