00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #pragma once
00027
00028 #include "cinder/Cinder.h"
00029 #include "cinder/Area.h"
00030
00031 namespace cinder {
00032
00033 typedef std::shared_ptr<class ImageSource> ImageSourceRef;
00034
00036 template<typename T>
00037 class ChannelT {
00038 protected:
00040 struct Obj {
00041 Obj( int32_t width, int32_t height );
00042 Obj( int32_t aWidth, int32_t aHeight, int32_t aRowBytes, uint8_t aIncrement, bool aOwnsData, T *aData );
00043 ~Obj();
00044
00045 int32_t mWidth, mHeight, mRowBytes;
00046 T *mData;
00047 uint8_t mIncrement;
00048 bool mOwnsData;
00049
00050 void (*mDeallocatorFunc)(void *refcon);
00051 void *mDeallocatorRefcon;
00052 };
00054
00055 public:
00057 ChannelT() {}
00059 ChannelT( int32_t width, int32_t height );
00061 ChannelT( int32_t width, int32_t height, int32_t rowBytes, uint8_t increment, T *data );
00063 ChannelT( ImageSourceRef imageSource );
00064
00065 operator ImageSourceRef() const;
00066
00068 ChannelT clone( bool copyPixels = true ) const;
00070 ChannelT clone( const Area &area, bool copyPixels = true ) const;
00071
00073 int32_t getWidth() const { return mObj->mWidth; }
00075 int32_t getHeight() const { return mObj->mHeight; }
00077 Vec2i getSize() const { return Vec2i( mObj->mWidth, mObj->mHeight ); }
00079 float getAspectRatio() const { return mObj->mWidth / (float)mObj->mHeight; }
00081 Area getBounds() const { return Area( 0, 0, mObj->mWidth, mObj->mHeight ); }
00083 int32_t getRowBytes() const { return mObj->mRowBytes; }
00085 uint8_t getIncrement() const { return mObj->mIncrement; }
00087 bool isPlanar() const { return mObj->mIncrement == 1; }
00088
00090 T* getData() { return mObj->mData; }
00092 const T* getData() const { return mObj->mData; }
00094 T* getData( const Vec2i &offset ) { return reinterpret_cast<T*>( reinterpret_cast<unsigned char*>( mObj->mData + offset.x * mObj->mIncrement ) + offset.y * mObj->mRowBytes ); }
00096 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 ); }
00098 T* getData( int32_t x, int32_t y ) { return reinterpret_cast<T*>( reinterpret_cast<unsigned char*>( mObj->mData + x * mObj->mIncrement ) + y * mObj->mRowBytes ); }
00100 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 ); }
00101
00103 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 ); }
00105 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; }
00106
00108 void copyFrom( const ChannelT<T> &srcChannel, const Area &srcArea, const Vec2i &relativeOffset = Vec2i::zero() );
00109
00111 T areaAverage( const Area &area ) const;
00112
00114 void setDeallocator( void(*aDeallocatorFunc)( void * ), void *aDeallocatorRefcon );
00115
00117 typedef std::shared_ptr<Obj> ChannelT::*unspecified_bool_type;
00118 operator unspecified_bool_type() const { return ( mObj.get() == 0 ) ? 0 : &ChannelT::mObj; }
00119 void reset() { mObj.reset(); }
00121
00123 class Iter {
00124 public:
00125 Iter( ChannelT<T> &channelT, const Area &area )
00126 : mInc( channelT.getIncrement() ), mRowInc( channelT.getRowBytes() )
00127 {
00128 Area clippedArea( area.getClipBy( channelT.getBounds() ) );
00129 mWidth = clippedArea.getWidth();
00130 mHeight = clippedArea.getHeight();
00131 mLinePtr = reinterpret_cast<uint8_t*>( channelT.getData( clippedArea.getUL() ) );
00132 mPtr = reinterpret_cast<T*>( mLinePtr );
00133 mStartX = mX = clippedArea.getX1();
00134 mStartY = mY = clippedArea.getY1();
00135 mEndX = clippedArea.getX2();
00136 mEndY = clippedArea.getY2();
00137
00138 mY = clippedArea.getY1() - 1;
00139 mLinePtr -= mRowInc;
00140 }
00141
00143 T& v() const { return *mPtr; }
00145 T& v( int32_t xOff, int32_t yOff ) const { return mPtr[xOff * mInc + yOff * mRowInc]; }
00147 T& vClamped( int32_t xOff, int32_t yOff ) const
00148 { xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
00149 return *(T*)((uint8_t*)( mPtr + xOff * mInc ) + yOff * mRowInc); }
00150
00152 const int32_t x() const { return mX; }
00154 const int32_t y() const { return mY; }
00156 Vec2i getPos() const { return Vec2i( mX, mY ); }
00157
00159 bool pixel() {
00160 ++mX;
00161 mPtr += mInc;
00162 return mX < mEndX;
00163 }
00164
00166 bool line() {
00167 ++mY;
00168 mLinePtr += mRowInc;
00169 mPtr = reinterpret_cast<T*>( mLinePtr );
00170
00171 mPtr -= mInc;
00172 mX = mStartX - 1;
00173 return mY < mEndY;
00174 }
00175
00177 int32_t getWidth() { return mWidth; }
00179 int32_t getHeight() { return mHeight; }
00180
00182 uint8_t mInc;
00183 uint8_t *mLinePtr;
00184 T *mPtr;
00185 int32_t mRowInc, mWidth, mHeight;
00186 int32_t mX, mY, mStartX, mStartY, mEndX, mEndY;
00188 };
00189
00191 class ConstIter {
00192 public:
00193 ConstIter( const ChannelT<T> &channelT, const Area &area )
00194 : mInc( channelT.getIncrement() ), mRowInc( channelT.getRowBytes() )
00195 {
00196 Area clippedArea( area.getClipBy( channelT.getBounds() ) );
00197 mWidth = clippedArea.getWidth();
00198 mHeight = clippedArea.getHeight();
00199 mLinePtr = reinterpret_cast<const uint8_t*>( channelT.getData( clippedArea.getUL() ) );
00200 mPtr = reinterpret_cast<const T*>( mLinePtr );
00201 mStartX = mX = clippedArea.getX1();
00202 mStartY = mY = clippedArea.getY1();
00203 mEndX = clippedArea.getX2();
00204 mEndY = clippedArea.getY2();
00205
00206 mY = clippedArea.getY1() - 1;
00207 mLinePtr -= mRowInc;
00208 }
00209
00211 const T& v() const { return *mPtr; }
00213 const T& v( int32_t xOff, int32_t yOff ) const { return mPtr[xOff * mInc + yOff * mRowInc]; }
00215 const T& vClamped( int32_t xOff, int32_t yOff ) const
00216 { xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
00217 return *(T*)((uint8_t*)( mPtr + xOff * mInc ) + yOff * mRowInc); }
00218
00220 const int32_t x() const { return mX; }
00222 const int32_t y() const { return mY; }
00224 Vec2i getPos() const { return Vec2i( mX, mY ); }
00225
00227 bool pixel() {
00228 ++mX;
00229 mPtr += mInc;
00230 return mX < mEndX;
00231 }
00232
00234 bool line() {
00235 ++mY;
00236 mLinePtr += mRowInc;
00237 mPtr = reinterpret_cast<const T*>( mLinePtr );
00238
00239 mPtr -= mInc;
00240 mX = mStartX - 1;
00241 return mY < mEndY;
00242 }
00243
00245 int32_t getWidth() { return mWidth; }
00247 int32_t getHeight() { return mHeight; }
00248
00250 uint8_t mInc;
00251 const uint8_t *mLinePtr;
00252 const T *mPtr;
00253 int32_t mRowInc, mWidth, mHeight;
00254 int32_t mX, mY, mStartX, mStartY, mEndX, mEndY;
00256 };
00257
00259 Iter getIter() { return Iter( *this, this->getBounds() ); }
00261 Iter getIter( const Area &area ) { return Iter( *this, area ); }
00263 ConstIter getIter() const { return ConstIter( *this, this->getBounds() ); }
00265 ConstIter getIter( const Area &area ) const { return ConstIter( *this, area ); }
00266
00267 protected:
00268 std::shared_ptr<Obj> mObj;
00269 };
00270
00271
00273 typedef ChannelT<uint8_t> Channel;
00275 typedef ChannelT<uint8_t> Channel8u;
00277 typedef ChannelT<uint16_t> Channel16u;
00279 typedef ChannelT<float> Channel32f;
00280
00281 }