00001 /* 00002 Copyright (c) 2010, The Cinder Project, All rights reserved. 00003 This code is intended for use with the Cinder C++ library: http://libcinder.org 00004 00005 Portions Copyright (c) 2010, The Barbarian Group 00006 All rights reserved. 00007 00008 Redistribution and use in source and binary forms, with or without modification, are permitted provided that 00009 the following conditions are met: 00010 00011 * Redistributions of source code must retain the above copyright notice, this list of conditions and 00012 the following disclaimer. 00013 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and 00014 the following disclaimer in the documentation and/or other materials provided with the distribution. 00015 00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED 00017 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 00018 PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR 00019 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED 00020 TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 00021 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 00022 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00023 POSSIBILITY OF SUCH DAMAGE. 00024 */ 00025 00026 #pragma once 00027 00028 #include "cinder/Cinder.h" 00029 #include "cinder/Area.h" 00030 #include "cinder/Channel.h" 00031 #include "cinder/ChanTraits.h" 00032 #include "cinder/Color.h" 00033 00034 #include <boost/logic/tribool.hpp> 00035 00036 namespace cinder { 00037 00039 class SurfaceChannelOrder { 00040 public: 00041 SurfaceChannelOrder() : mCode( UNSPECIFIED ), mRed( INVALID ), mGreen( INVALID ), mBlue( INVALID ), mAlpha( INVALID ), mPixelInc( INVALID ) {} 00042 SurfaceChannelOrder( int aCode ); 00043 SurfaceChannelOrder( const SurfaceChannelOrder &aOrder ); 00044 00045 // static ChannelOrder GetPlatformNativeChannelOrder( bool includeAlpha ); 00046 00047 uint8_t getRedOffset() const { return mRed; } 00048 uint8_t getGreenOffset() const { return mGreen; } 00049 uint8_t getBlueOffset() const { return mBlue; } 00050 uint8_t getAlphaOffset() const { return mAlpha; } 00051 bool hasAlpha() const { return ( mAlpha != INVALID ) ? true : false; } 00052 uint8_t getPixelInc() const { return mPixelInc; } 00053 int getCode() const { return mCode; } 00054 00055 bool operator==( const SurfaceChannelOrder& sco ) const 00056 { 00057 return mCode == sco.mCode; 00058 } 00059 00060 enum { CHAN_RED, CHAN_GREEN, CHAN_BLUE, CHAN_ALPHA, INVALID = 255 }; 00061 enum { RGBA, BGRA, ARGB, ABGR, RGBX, BGRX, XRGB, XBGR, RGB, BGR, UNSPECIFIED }; // Codes 00062 00063 int getImageIoChannelOrder() const; 00064 00065 private: 00066 void set( uint8_t aRed, uint8_t aGreen, uint8_t aBlue, uint8_t aAlpha, uint8_t aPixelInc ); 00067 int mCode; // the enum 00068 uint8_t mRed, mGreen, mBlue, mAlpha, mPixelInc; 00069 00070 }; 00071 00073 class SurfaceConstraints { 00074 public: 00075 virtual ~SurfaceConstraints() {} 00076 00077 virtual SurfaceChannelOrder getChannelOrder( bool alpha ) const { return ( alpha ) ? SurfaceChannelOrder::RGBA : SurfaceChannelOrder::RGB; } 00078 virtual int32_t getRowBytes( int requestedWidth, const SurfaceChannelOrder &sco, int elementSize ) const { return requestedWidth * elementSize * sco.getPixelInc(); } 00079 }; 00080 00081 class SurfaceConstraintsDefault : public SurfaceConstraints { 00082 }; 00083 00084 typedef std::shared_ptr<class ImageSource> ImageSourceRef; 00085 typedef std::shared_ptr<class ImageTarget> ImageTargetRef; 00086 00087 template<typename T> 00089 class SurfaceT { 00090 private: 00092 struct Obj { 00093 Obj( int32_t aWidth, int32_t aHeight, SurfaceChannelOrder aChannelOrder, T *aData, bool aOwnsData, int32_t aRowBytes ); 00094 ~Obj(); 00095 00096 void initChannels(); 00097 void setChannelOrder( const SurfaceChannelOrder &aChannelOrder ); 00098 void setDeallocator( void(*aDeallocatorFunc)( void * ), void *aDeallocatorRefcon ); 00099 00100 int32_t mWidth, mHeight, mRowBytes; 00101 bool mIsPremultiplied; 00102 T *mData; 00103 bool mOwnsData; 00104 SurfaceChannelOrder mChannelOrder; 00105 ChannelT<T> mChannels[4]; 00106 00107 void (*mDeallocatorFunc)(void *refcon); 00108 void *mDeallocatorRefcon; 00109 }; 00111 00112 public: 00114 SurfaceT() {} 00120 SurfaceT( int32_t width, int32_t height, bool alpha, SurfaceChannelOrder channelOrder = SurfaceChannelOrder::UNSPECIFIED ); 00121 SurfaceT( int32_t width, int32_t height, bool alpha, const SurfaceConstraints &constraints ); 00123 SurfaceT( T *data, int32_t width, int32_t height, int32_t rowBytes, SurfaceChannelOrder channelOrder ); 00129 SurfaceT( ImageSourceRef imageSource, const SurfaceConstraints &constraints = SurfaceConstraintsDefault(), boost::tribool alpha = boost::logic::indeterminate ); 00130 00131 operator ImageSourceRef() const; 00132 operator ImageTargetRef(); 00133 00135 int32_t getWidth() const { return mObj->mWidth; } 00137 int32_t getHeight() const { return mObj->mHeight; } 00139 Vec2i getSize() const { return Vec2i( mObj->mWidth, mObj->mHeight ); } 00141 float getAspectRatio() const { return mObj->mWidth / (float)mObj->mHeight; } 00143 Area getBounds() const { return Area( 0, 0, mObj->mWidth, mObj->mHeight ); } 00145 bool hasAlpha() const { return mObj->mChannelOrder.hasAlpha(); } 00147 bool isPremultiplied() const { return mObj->mIsPremultiplied; } 00149 bool setPremultiplied( bool premult = true ) const { return mObj->mIsPremultiplied = premult; } 00151 int32_t getRowBytes() const { return mObj->mRowBytes; } 00153 uint8_t getPixelInc() const { return mObj->mChannelOrder.getPixelInc(); } 00154 00156 SurfaceT clone( bool copyPixels = true ) const; 00158 SurfaceT clone( const Area &area, bool copyPixels = true ) const; 00159 00161 T* getData() { return mObj->mData; } 00162 const T* getData() const { return mObj->mData; } 00163 T* getData( const Vec2i &offset ) { return reinterpret_cast<T*>( reinterpret_cast<unsigned char*>( mObj->mData + offset.x * getPixelInc() ) + offset.y * mObj->mRowBytes ); } 00164 const T* getData( const Vec2i &offset ) const { return reinterpret_cast<T*>( reinterpret_cast<unsigned char*>( mObj->mData + offset.x * getPixelInc() ) + offset.y * mObj->mRowBytes ); } 00166 T* getDataRed( const Vec2i &offset ) { return getData( offset ) + getRedOffset(); } 00167 const T* getDataRed( const Vec2i &offset ) const { return getData( offset ) + getRedOffset(); } 00169 T* getDataGreen( const Vec2i &offset ) { return getData( offset ) + getGreenOffset(); } 00170 const T* getDataGreen( const Vec2i &offset ) const { return getData( offset ) + getGreenOffset(); } 00172 T* getDataBlue( const Vec2i &offset ) { return getData( offset ) + getBlueOffset(); } 00173 const T* getDataBlue( const Vec2i &offset ) const { return getData( offset ) + getBlueOffset(); } 00175 T* getDataAlpha( const Vec2i &offset ) { return getData( offset ) + getAlphaOffset(); } 00176 const T* getDataAlpha( const Vec2i &offset ) const { return getData( offset ) + getAlphaOffset(); } 00177 00179 void setDeallocator( void(*aDeallocatorFunc)( void * ), void *aDeallocatorRefcon ); 00180 00182 const SurfaceChannelOrder& getChannelOrder() const { return mObj->mChannelOrder; } 00184 uint8_t getRedOffset() const { return mObj->mChannelOrder.getRedOffset(); } 00186 uint8_t getGreenOffset() const { return mObj->mChannelOrder.getGreenOffset(); } 00188 uint8_t getBlueOffset() const { return mObj->mChannelOrder.getBlueOffset(); } 00190 uint8_t getAlphaOffset() const { return mObj->mChannelOrder.getAlphaOffset(); } 00192 void setChannelOrder( const SurfaceChannelOrder &aChannelOrder ); 00193 00195 ChannelT<T>& getChannel( uint8_t channelIndex ) { return mObj->mChannels[channelIndex]; } 00197 const ChannelT<T>& getChannel( uint8_t channelIndex ) const { return mObj->mChannels[channelIndex]; } 00198 00200 ChannelT<T>& getChannelRed() { return mObj->mChannels[SurfaceChannelOrder::CHAN_RED]; } 00202 ChannelT<T>& getChannelGreen() { return mObj->mChannels[SurfaceChannelOrder::CHAN_GREEN]; } 00204 ChannelT<T>& getChannelBlue() { return mObj->mChannels[SurfaceChannelOrder::CHAN_BLUE]; } 00206 ChannelT<T>& getChannelAlpha() { return mObj->mChannels[SurfaceChannelOrder::CHAN_ALPHA]; } 00207 00209 const ChannelT<T>& getChannelRed() const { return mObj->mChannels[SurfaceChannelOrder::CHAN_RED]; } 00211 const ChannelT<T>& getChannelGreen() const { return mObj->mChannels[SurfaceChannelOrder::CHAN_GREEN]; } 00213 const ChannelT<T>& getChannelBlue() const { return mObj->mChannels[SurfaceChannelOrder::CHAN_BLUE]; } 00215 const ChannelT<T>& getChannelAlpha() const { return mObj->mChannels[SurfaceChannelOrder::CHAN_ALPHA]; } 00216 00218 ColorAT<T> getPixel( 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 ); const T *p = getData( pos ); return ColorAT<T>( p[getRedOffset()], p[getGreenOffset()], p[getBlueOffset()], ( hasAlpha() ) ? p[getAlphaOffset()] : CHANTRAIT<T>::max() ); } 00220 void setPixel( Vec2i pos, const ColorT<T> &c ) { pos.x = constrain<int32_t>( pos.x, 0, mObj->mWidth - 1); pos.y = constrain<int32_t>( pos.y, 0, mObj->mHeight - 1 ); T *p = getData( pos ); p[getRedOffset()] = c.r; p[getGreenOffset()] = c.g; p[getBlueOffset()] = c.b; } 00222 void setPixel( Vec2i pos, const ColorAT<T> &c ) { pos.x = constrain<int32_t>( pos.x, 0, mObj->mWidth - 1); pos.y = constrain<int32_t>( pos.y, 0, mObj->mHeight - 1 ); T *p = getData( pos ); p[getRedOffset()] = c.r; p[getGreenOffset()] = c.g; p[getBlueOffset()] = c.b; if( hasAlpha() ) p[getAlphaOffset()] = c.a; } 00223 00225 void copyFrom( const SurfaceT<T> &srcSurface, const Area &srcArea, const Vec2i &relativeOffset = Vec2i::zero() ); 00226 00228 ColorT<T> areaAverage( const Area &area ) const; 00229 00231 typedef std::shared_ptr<Obj> SurfaceT::*unspecified_bool_type; 00232 operator unspecified_bool_type() const { return ( mObj.get() == 0 ) ? 0 : &SurfaceT::mObj; } 00233 void reset() { mObj.reset(); } 00235 00236 private: 00237 std::shared_ptr<Obj> mObj; 00238 00239 void init( ImageSourceRef imageSource, const SurfaceConstraints &constraints = SurfaceConstraintsDefault(), boost::tribool alpha = boost::logic::indeterminate ); 00240 00241 void copyRawSameChannelOrder( const SurfaceT<T> &srcSurface, const Area &srcArea, const Vec2i &absoluteOffset ); 00242 void copyRawRgba( const SurfaceT<T> &srcSurface, const Area &srcArea, const Vec2i &absoluteOffset ); 00243 void copyRawRgbFullAlpha( const SurfaceT<T> &srcSurface, const Area &srcArea, const Vec2i &absoluteOffset ); 00244 void copyRawRgb( const SurfaceT<T> &srcSurface, const Area &srcArea, const Vec2i &absoluteOffset ); 00245 00246 public: 00247 00249 class Iter { 00250 public: 00251 Iter( SurfaceT<T> &SurfaceT, const Area &area ) 00252 : mRedOff( SurfaceT.getRedOffset() ), mGreenOff( SurfaceT.getGreenOffset() ), 00253 mBlueOff( SurfaceT.getBlueOffset() ), mAlphaOff( SurfaceT.getAlphaOffset() ), 00254 mInc( SurfaceT.getPixelInc() ), mRowInc( SurfaceT.getRowBytes() ) 00255 { 00256 Area clippedArea( area.getClipBy( SurfaceT.getBounds() ) ); 00257 mWidth = clippedArea.getWidth(); 00258 mHeight = clippedArea.getHeight(); 00259 mLinePtr = reinterpret_cast<uint8_t*>( SurfaceT.getData( clippedArea.getUL() ) ); 00260 mPtr = reinterpret_cast<T*>( mLinePtr ); 00261 mStartX = mX = clippedArea.getX1(); 00262 mStartY = mY = clippedArea.getY1(); 00263 mEndX = clippedArea.getX2(); 00264 mEndY = clippedArea.getY2(); 00265 // in order to be at the right place after an initial call to line(), we need to back up one line 00266 mY = clippedArea.getY1() - 1; 00267 mLinePtr -= mRowInc; 00268 } 00270 T& r() const { return mPtr[mRedOff]; } 00272 T& g() const { return mPtr[mGreenOff]; } 00274 T& b() const { return mPtr[mBlueOff]; } 00276 T& a() const { return mPtr[mAlphaOff]; } 00277 00279 T& r( int32_t xOff, int32_t yOff ) const { return mPtr[mRedOff + xOff * mInc + yOff * mRowInc]; } 00281 T& g( int32_t xOff, int32_t yOff ) const { return mPtr[mGreenOff + xOff * mInc + yOff * mRowInc]; } 00283 T& b( int32_t xOff, int32_t yOff ) const { return mPtr[mBlueOff + xOff * mInc + yOff * mRowInc]; } 00285 T& a( int32_t xOff, int32_t yOff ) const { return mPtr[mAlphaOff + xOff * mInc + yOff * mRowInc]; } 00286 00288 T& rClamped( int32_t xOff, int32_t yOff ) const 00289 { xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY; 00290 return *(T*)((uint8_t*)( mPtr + mRedOff + xOff * mInc ) + yOff * mRowInc); } 00292 T& gClamped( int32_t xOff, int32_t yOff ) const 00293 { xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY; 00294 return *(T*)((uint8_t*)( mPtr + mGreenOff + xOff * mInc ) + yOff * mRowInc); } 00296 T& bClamped( int32_t xOff, int32_t yOff ) const 00297 { xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY; 00298 return *(T*)((uint8_t*)( mPtr + mBlueOff + xOff * mInc ) + yOff * mRowInc); } 00300 T& aClamped( int32_t xOff, int32_t yOff ) const 00301 { xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY; 00302 return *(T*)((uint8_t*)( mPtr + mAlphaOff + xOff * mInc ) + yOff * mRowInc); } 00303 00305 const int32_t x() const { return mX; } 00307 const int32_t y() const { return mY; } 00309 Vec2i getPos() const { return Vec2i( mX, mY ); } 00310 00312 bool pixel() { 00313 ++mX; 00314 mPtr += mInc; 00315 return mX < mEndX; 00316 } 00317 00319 bool line() { 00320 ++mY; 00321 mLinePtr += mRowInc; 00322 mPtr = reinterpret_cast<T*>( mLinePtr ); 00323 // in order to be at the right place after an initial call to pixel(), we need to back up one pixel 00324 mPtr -= mInc; 00325 mX = mStartX - 1; 00326 return mY < mEndY; 00327 } 00328 00330 int32_t getWidth() const { return mWidth; } 00332 int32_t getHeight() const { return mHeight; } 00333 00335 uint8_t mRedOff, mGreenOff, mBlueOff, mAlphaOff, mInc; 00336 uint8_t *mLinePtr; 00337 T *mPtr; 00338 int32_t mRowInc, mWidth, mHeight; 00339 int32_t mX, mY, mStartX, mStartY, mEndX, mEndY; 00341 }; 00342 00344 class ConstIter { 00345 public: 00346 ConstIter( const Iter &iter ) { 00347 mRedOff = iter.mRedOff; 00348 mGreenOff = iter.mGreenOff; 00349 mBlueOff = iter.mBlueOff; 00350 mAlphaOff = iter.mAlphaOff; 00351 mInc = iter.mInc; 00352 mRowInc = iter.mRowInc; 00353 mWidth = iter.mWidth; 00354 mHeight = iter.mHeight; 00355 mLinePtr = iter.mLinePtr; 00356 mPtr = iter.mPtr; 00357 mStartX = iter.mStartX; 00358 mX = iter.mX; 00359 mStartY = iter.mStartY; 00360 mY = iter.mY; 00361 mEndX = iter.mEndX; 00362 mEndY = iter.mEndY; 00363 } 00364 00365 ConstIter( const SurfaceT<T> &SurfaceT, const Area &area ) 00366 : mRedOff( SurfaceT.getRedOffset() ), mGreenOff( SurfaceT.getGreenOffset() ), 00367 mBlueOff( SurfaceT.getBlueOffset() ), mAlphaOff( SurfaceT.getAlphaOffset() ), 00368 mInc( SurfaceT.getPixelInc() ), mRowInc( SurfaceT.getRowBytes() ) 00369 { 00370 Area clippedArea( area.getClipBy( SurfaceT.getBounds() ) ); 00371 mWidth = clippedArea.getWidth(); 00372 mHeight = clippedArea.getHeight(); 00373 mLinePtr = reinterpret_cast<const uint8_t*>( SurfaceT.getData( clippedArea.getUL() ) ); 00374 mPtr = reinterpret_cast<const T*>( mLinePtr ); 00375 mStartX = mX = clippedArea.getX1(); 00376 mStartY = mY = clippedArea.getY1(); 00377 mEndX = clippedArea.getX2(); 00378 mEndY = clippedArea.getY2(); 00379 // in order to be at the right place after an initial call to line(), we need to back up one line 00380 mY = clippedArea.getY1() - 1; 00381 mLinePtr -= mRowInc; 00382 } 00383 00385 const T& r() const { return mPtr[mRedOff]; } 00387 const T& g() const { return mPtr[mGreenOff]; } 00389 const T& b() const { return mPtr[mBlueOff]; } 00391 const T& a() const { return mPtr[mAlphaOff]; } 00392 00394 const T& r( int32_t xOff, int32_t yOff ) const { return mPtr[mRedOff + xOff * mInc + yOff * mRowInc]; } 00396 const T& g( int32_t xOff, int32_t yOff ) const { return mPtr[mGreenOff + xOff * mInc + yOff * mRowInc]; } 00398 const T& b( int32_t xOff, int32_t yOff ) const { return mPtr[mBlueOff + xOff * mInc + yOff * mRowInc]; } 00400 const T& a( int32_t xOff, int32_t yOff ) const { return mPtr[mAlphaOff + xOff * mInc + yOff * mRowInc]; } 00401 00403 const T& rClamped( int32_t xOff, int32_t yOff ) const 00404 { xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY; 00405 return *(T*)((uint8_t*)( mPtr + mRedOff + xOff * mInc ) + yOff * mRowInc); } 00407 const T& gClamped( int32_t xOff, int32_t yOff ) const 00408 { xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY; 00409 return *(T*)((uint8_t*)( mPtr + mGreenOff + xOff * mInc ) + yOff * mRowInc); } 00411 const T& bClamped( int32_t xOff, int32_t yOff ) const 00412 { xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY; 00413 return *(T*)((uint8_t*)( mPtr + mBlueOff + xOff * mInc ) + yOff * mRowInc); } 00415 const T& aClamped( int32_t xOff, int32_t yOff ) const 00416 { xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY; 00417 return *(T*)((uint8_t*)( mPtr + mAlphaOff + xOff * mInc ) + yOff * mRowInc); } 00418 00420 const int32_t x() const { return mX; } 00422 const int32_t y() const { return mY; } 00424 Vec2i getPos() const { return Vec2i( mX, mY ); } 00425 00427 bool pixel() { 00428 ++mX; 00429 mPtr += mInc; 00430 return mX < mEndX; 00431 } 00432 00434 bool line() { 00435 ++mY; 00436 mLinePtr += mRowInc; 00437 mPtr = reinterpret_cast<const T*>( mLinePtr ); 00438 // in order to be at the right place after an initial call to pixel(), we need to back up one pixel 00439 mPtr -= mInc; 00440 mX = mStartX - 1; 00441 return mY < mEndY; 00442 } 00443 00445 int32_t getWidth() const { return mWidth; } 00447 int32_t getHeight() const { return mHeight; } 00448 00450 uint8_t mRedOff, mGreenOff, mBlueOff, mAlphaOff, mInc; 00451 const uint8_t *mLinePtr; 00452 const T *mPtr; 00453 int32_t mRowInc, mWidth, mHeight; 00454 int32_t mX, mY, mStartX, mStartY, mEndX, mEndY; 00456 }; 00457 00459 Iter getIter() { return Iter( *this, this->getBounds() ); } 00461 Iter getIter( const Area &area ) { return Iter( *this, area ); } 00463 ConstIter getIter() const { return ConstIter( *this, this->getBounds() ); } 00465 ConstIter getIter( const Area &area ) const { return ConstIter( *this, area ); } 00466 }; 00467 00468 class SurfaceExc : public std::exception { 00469 virtual const char* what() const throw() { 00470 return "Surface exception"; 00471 } 00472 }; 00473 00474 class SurfaceConstraintsExc : public SurfaceExc { 00475 virtual const char* what() const throw() { 00476 return "Surface exception: does not conform to expected SurfaceConstraints"; 00477 } 00478 }; 00479 00481 typedef SurfaceT<uint8_t> Surface; 00483 typedef SurfaceT<uint8_t> Surface8u; 00485 typedef SurfaceT<uint16_t> Surface16u; 00487 typedef SurfaceT<float> Surface32f; 00488 00489 } // namespace cinder