Cinder

  • Main Page
  • Related Pages
  • Namespaces
  • Classes
  • Files
  • Examples
  • File List
  • File Members

include/cinder/Surface.h

Go to the documentation of this file.
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    copyRawRgb( const SurfaceT<T> &srcSurface, const Area &srcArea, const Vec2i &absoluteOffset );
00244  
00245  public:
00246     
00248     class Iter {
00249      public:
00250         Iter( SurfaceT<T> &SurfaceT, const Area &area ) 
00251             : mRedOff( SurfaceT.getRedOffset() ), mGreenOff( SurfaceT.getGreenOffset() ), 
00252                 mBlueOff( SurfaceT.getBlueOffset() ), mAlphaOff( SurfaceT.getAlphaOffset() ),
00253                 mInc( SurfaceT.getPixelInc() ), mRowInc( SurfaceT.getRowBytes() )
00254         {
00255             Area clippedArea( area.getClipBy( SurfaceT.getBounds() ) );
00256             mWidth = clippedArea.getWidth();
00257             mHeight = clippedArea.getHeight();
00258             mLinePtr = reinterpret_cast<uint8_t*>( SurfaceT.getData( clippedArea.getUL() ) );
00259             mPtr = reinterpret_cast<T*>( mLinePtr );
00260             mStartX = mX = clippedArea.getX1();
00261             mStartY = mY = clippedArea.getY1();
00262             mEndX = clippedArea.getX2();
00263             mEndY = clippedArea.getY2();
00264             // in order to be at the right place after an initial call to line(), we need to back up one line
00265             mY = clippedArea.getY1() - 1;
00266             mLinePtr -= mRowInc;
00267         }
00269         T&          r() const { return mPtr[mRedOff]; }
00271         T&          g() const { return mPtr[mGreenOff]; }
00273         T&          b() const { return mPtr[mBlueOff]; }
00275         T&          a() const { return mPtr[mAlphaOff]; }
00276 
00278         T&          r( int32_t xOff, int32_t yOff ) const { return mPtr[mRedOff + xOff * mInc + yOff * mRowInc]; }
00280         T&          g( int32_t xOff, int32_t yOff ) const { return mPtr[mGreenOff + xOff * mInc + yOff * mRowInc]; }
00282         T&          b( int32_t xOff, int32_t yOff ) const { return mPtr[mBlueOff + xOff * mInc + yOff * mRowInc]; } 
00284         T&          a( int32_t xOff, int32_t yOff ) const { return mPtr[mAlphaOff + xOff * mInc + yOff * mRowInc]; }
00285 
00287         T&          rClamped( int32_t xOff, int32_t yOff ) const
00288                         {   xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
00289                             return *(T*)((uint8_t*)( mPtr + mRedOff + xOff * mInc ) + yOff * mRowInc); }
00291         T&          gClamped( int32_t xOff, int32_t yOff ) const
00292                         {   xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
00293                             return *(T*)((uint8_t*)( mPtr + mGreenOff + xOff * mInc ) + yOff * mRowInc); }
00295         T&          bClamped( int32_t xOff, int32_t yOff ) const
00296                         {   xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
00297                             return *(T*)((uint8_t*)( mPtr + mBlueOff + xOff * mInc ) + yOff * mRowInc); }
00299         T&          aClamped( int32_t xOff, int32_t yOff ) const
00300                         {   xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
00301                             return *(T*)((uint8_t*)( mPtr + mAlphaOff + xOff * mInc ) + yOff * mRowInc); }
00302 
00304         const int32_t   x() const { return mX; }
00306         const int32_t   y() const { return mY; }
00308         Vec2i           getPos() const { return Vec2i( mX, mY ); }
00309 
00311         bool pixel() {
00312             ++mX;
00313             mPtr += mInc;
00314             return mX < mEndX;
00315         }
00316         
00318         bool line() {
00319             ++mY;
00320             mLinePtr += mRowInc;
00321             mPtr = reinterpret_cast<T*>( mLinePtr );
00322             // in order to be at the right place after an initial call to pixel(), we need to back up one pixel
00323             mPtr -= mInc;
00324             mX = mStartX - 1;
00325             return mY < mEndY;
00326         }
00327         
00329         int32_t     getWidth() const { return mWidth; }
00331         int32_t     getHeight() const { return mHeight; }
00332 
00334         uint8_t             mRedOff, mGreenOff, mBlueOff, mAlphaOff, mInc;
00335         uint8_t             *mLinePtr;
00336         T                   *mPtr;
00337         int32_t             mRowInc, mWidth, mHeight;
00338         int32_t             mX, mY, mStartX, mStartY, mEndX, mEndY;
00340     };
00341 
00343     class ConstIter {
00344      public:
00345         ConstIter( const Iter &iter ) {
00346             mRedOff = iter.mRedOff;
00347             mGreenOff = iter.mGreenOff;
00348             mBlueOff = iter.mBlueOff;
00349             mAlphaOff = iter.mAlphaOff;
00350             mInc = iter.mInc;       
00351             mRowInc = iter.mRowInc;
00352             mWidth = iter.mWidth;
00353             mHeight = iter.mHeight;
00354             mLinePtr = iter.mLinePtr;
00355             mPtr = iter.mPtr;
00356             mStartX = iter.mStartX;
00357             mX = iter.mX;           
00358             mStartY = iter.mStartY;
00359             mY = iter.mY;
00360             mEndX = iter.mEndX;
00361             mEndY = iter.mEndY;
00362         }
00363         
00364         ConstIter( const SurfaceT<T> &SurfaceT, const Area &area ) 
00365             : mRedOff( SurfaceT.getRedOffset() ), mGreenOff( SurfaceT.getGreenOffset() ), 
00366                 mBlueOff( SurfaceT.getBlueOffset() ), mAlphaOff( SurfaceT.getAlphaOffset() ),
00367                 mInc( SurfaceT.getPixelInc() ), mRowInc( SurfaceT.getRowBytes() )
00368         {
00369             Area clippedArea( area.getClipBy( SurfaceT.getBounds() ) );
00370             mWidth = clippedArea.getWidth();
00371             mHeight = clippedArea.getHeight();
00372             mLinePtr = reinterpret_cast<const uint8_t*>( SurfaceT.getData( clippedArea.getUL() ) );
00373             mPtr = reinterpret_cast<const T*>( mLinePtr );
00374             mStartX = mX = clippedArea.getX1();
00375             mStartY = mY = clippedArea.getY1();
00376             mEndX = clippedArea.getX2();
00377             mEndY = clippedArea.getY2();
00378             // in order to be at the right place after an initial call to line(), we need to back up one line
00379             mY = clippedArea.getY1() - 1;
00380             mLinePtr -= mRowInc;
00381         }
00382         
00384         const T&    r() const { return mPtr[mRedOff]; }
00386         const T&    g() const { return mPtr[mGreenOff]; }
00388         const T&    b() const { return mPtr[mBlueOff]; }    
00390         const T&    a() const { return mPtr[mAlphaOff]; }
00391 
00393         const T&    r( int32_t xOff, int32_t yOff ) const { return mPtr[mRedOff + xOff * mInc + yOff * mRowInc]; }
00395         const T&    g( int32_t xOff, int32_t yOff ) const { return mPtr[mGreenOff + xOff * mInc + yOff * mRowInc]; }
00397         const T&    b( int32_t xOff, int32_t yOff ) const { return mPtr[mBlueOff + xOff * mInc + yOff * mRowInc]; } 
00399         const T&    a( int32_t xOff, int32_t yOff ) const { return mPtr[mAlphaOff + xOff * mInc + yOff * mRowInc]; }
00400 
00402         const T&    rClamped( int32_t xOff, int32_t yOff ) const
00403                         {   xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
00404                             return *(T*)((uint8_t*)( mPtr + mRedOff + xOff * mInc ) + yOff * mRowInc); }
00406         const T&    gClamped( int32_t xOff, int32_t yOff ) const
00407                         {   xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
00408                             return *(T*)((uint8_t*)( mPtr + mGreenOff + xOff * mInc ) + yOff * mRowInc); }
00410         const T&    bClamped( int32_t xOff, int32_t yOff ) const
00411                         {   xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
00412                             return *(T*)((uint8_t*)( mPtr + mBlueOff + xOff * mInc ) + yOff * mRowInc); }
00414         const T&    aClamped( int32_t xOff, int32_t yOff ) const
00415                         {   xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
00416                             return *(T*)((uint8_t*)( mPtr + mAlphaOff + xOff * mInc ) + yOff * mRowInc); }
00417         
00419         const int32_t   x() const { return mX; }
00421         const int32_t   y() const { return mY; }
00423         Vec2i           getPos() const { return Vec2i( mX, mY ); }
00424 
00426         bool pixel() {
00427             ++mX;
00428             mPtr += mInc;
00429             return mX < mEndX;
00430         }
00431         
00433         bool line() {
00434             ++mY;
00435             mLinePtr += mRowInc;
00436             mPtr = reinterpret_cast<const T*>( mLinePtr );
00437             // in order to be at the right place after an initial call to pixel(), we need to back up one pixel
00438             mPtr -= mInc;
00439             mX = mStartX - 1;
00440             return mY < mEndY;
00441         }
00442         
00444         int32_t     getWidth() const { return mWidth; }
00446         int32_t     getHeight() const { return mHeight; }
00447 
00449         uint8_t             mRedOff, mGreenOff, mBlueOff, mAlphaOff, mInc;
00450         const uint8_t       *mLinePtr;
00451         const T             *mPtr;
00452         int32_t             mRowInc, mWidth, mHeight;
00453         int32_t             mX, mY, mStartX, mStartY, mEndX, mEndY;
00455     };
00456 
00458     Iter        getIter() { return Iter( *this, this->getBounds() ); }
00460     Iter        getIter( const Area &area ) { return Iter( *this, area ); }
00462     ConstIter   getIter() const { return ConstIter( *this, this->getBounds() ); }
00464     ConstIter   getIter( const Area &area ) const { return ConstIter( *this, area ); }
00465 };
00466 
00467 class SurfaceExc : public std::exception {
00468     virtual const char* what() const throw() {
00469         return "Surface exception";
00470     }
00471 };
00472 
00473 class SurfaceConstraintsExc : public SurfaceExc {
00474     virtual const char* what() const throw() {
00475         return "Surface exception: does not conform to expected SurfaceConstraints";
00476     }
00477 };
00478 
00480 typedef SurfaceT<uint8_t> Surface;
00482 typedef SurfaceT<uint8_t> Surface8u;    
00484 typedef SurfaceT<uint16_t> Surface16u;
00486 typedef SurfaceT<float> Surface32f;
00487 
00488 } // namespace cinder