Cinder

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

include/cinder/Surface.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 #include "cinder/Channel.h"
00028 #include "cinder/ChanTraits.h"
00029 #include "cinder/Color.h"
00030 
00031 #include <boost/logic/tribool.hpp>
00032 
00033 namespace cinder {
00034 
00035 class SurfaceChannelOrder {
00036   public:
00037     SurfaceChannelOrder() : mCode( UNSPECIFIED ), mRed( INVALID ), mGreen( INVALID ), mBlue( INVALID ), mAlpha( INVALID ), mPixelInc( INVALID ) {}
00038     SurfaceChannelOrder( int aCode );
00039     SurfaceChannelOrder( const SurfaceChannelOrder &aOrder );
00040         
00041 //  static ChannelOrder GetPlatformNativeChannelOrder( bool includeAlpha );
00042     
00043     uint8_t     getRedOffset() const { return mRed; }
00044     uint8_t     getGreenOffset() const { return mGreen; }
00045     uint8_t     getBlueOffset() const { return mBlue; }
00046     uint8_t     getAlphaOffset() const { return mAlpha; }
00047     bool        hasAlpha() const { return ( mAlpha != INVALID ) ? true : false; }
00048     uint8_t     getPixelInc() const { return mPixelInc; }
00049     int         getCode() const { return mCode; }
00050 
00051     bool operator==( const SurfaceChannelOrder& sco ) const 
00052     {
00053         return mCode == sco.mCode;
00054     }
00055 
00056     enum { CHAN_RED, CHAN_GREEN, CHAN_BLUE, CHAN_ALPHA, INVALID = 255 };    
00057     enum { RGBA, BGRA, ARGB, ABGR, RGBX, BGRX, XRGB, XBGR, RGB, BGR, UNSPECIFIED }; // Codes
00058 
00059     int         getImageIoChannelOrder() const;
00060 
00061   private:
00062     void        set( uint8_t aRed, uint8_t aGreen, uint8_t aBlue, uint8_t aAlpha, uint8_t aPixelInc );
00063     int         mCode; // the enum 
00064     uint8_t     mRed, mGreen, mBlue, mAlpha, mPixelInc;
00065     
00066 };
00067 
00069 class SurfaceConstraints {
00070  public:
00071     virtual ~SurfaceConstraints() {}
00072  
00073     virtual SurfaceChannelOrder getChannelOrder( bool alpha ) const { return ( alpha ) ? SurfaceChannelOrder::RGBA : SurfaceChannelOrder::RGB; }
00074     virtual int32_t             getRowBytes( int requestedWidth, const SurfaceChannelOrder &sco, int elementSize ) const { return requestedWidth * elementSize * sco.getPixelInc(); }
00075 };
00076 
00077 class SurfaceConstraintsDefault : public SurfaceConstraints {
00078 };
00079 
00080 typedef shared_ptr<class ImageSource> ImageSourceRef;
00081 
00082 template<typename T>
00083 class SurfaceT {
00084  private:
00086     struct Obj {
00087         Obj( int32_t aWidth, int32_t aHeight, SurfaceChannelOrder aChannelOrder, T *aData, bool aOwnsData, int32_t aRowBytes );
00088         ~Obj();
00089         
00090         void        initChannels();
00091         void        setData( T *aData, int32_t aWidth, int32_t aHeight, int32_t aRowBytes );
00092         void        setChannelOrder( const SurfaceChannelOrder &aChannelOrder );
00093         void        setDeallocator( void(*aDeallocatorFunc)( void * ), void *aDeallocatorRefcon );
00094     
00095         int32_t                     mWidth, mHeight, mRowBytes;
00096         bool                        mIsPremultiplied;
00097         T                           *mData;
00098         bool                        mOwnsData;
00099         SurfaceChannelOrder         mChannelOrder;
00100         ChannelT<T>                 mChannels[4];
00101         
00102         void                        (*mDeallocatorFunc)(void *refcon);
00103         void                        *mDeallocatorRefcon;
00104     };
00106 
00107  public:
00108     SurfaceT() {}
00109     SurfaceT( int32_t aWidth, int32_t aHeight, bool alpha, SurfaceChannelOrder aChannelOrder = SurfaceChannelOrder::UNSPECIFIED );
00110     SurfaceT( int32_t aWidth, int32_t aHeight, bool alpha, const SurfaceConstraints &constraints );
00111     SurfaceT( T *aData, int32_t aWidth, int32_t aHeight, int32_t aRowBytes, SurfaceChannelOrder aChannelOrder );
00112     SurfaceT( shared_ptr<class ImageSource> imageSource, const SurfaceConstraints &constraints = SurfaceConstraintsDefault(), boost::tribool alpha = boost::logic::indeterminate );
00113 
00114     operator ImageSourceRef() const;
00115 
00117     int32_t         getWidth() const { return mObj->mWidth; }
00119     int32_t         getHeight() const { return mObj->mHeight; }
00121     Vec2i           getSize() const { return Vec2i( mObj->mWidth, mObj->mHeight ); }
00123     float           getAspectRatio() const { return mObj->mWidth / (float)mObj->mHeight; }
00125     Area            getBounds() const { return Area( 0, 0, mObj->mWidth, mObj->mHeight ); }
00127     bool            hasAlpha() const { return mObj->mChannelOrder.hasAlpha(); }
00129     bool            isPremultiplied() const { return mObj->mIsPremultiplied; }
00131     bool            setPremultiplied( bool premult = true ) const { return mObj->mIsPremultiplied = premult; }
00133     int32_t         getRowBytes() const { return mObj->mRowBytes; }
00135     uint8_t         getPixelInc() const { return mObj->mChannelOrder.getPixelInc(); }
00136 
00138     SurfaceT            clone( bool copyPixels = true ) const;
00140     SurfaceT            clone( const Area &area, bool copyPixels = true ) const;
00141 
00142     T*                  getData() { return mObj->mData; }
00143     const T*            getData() const { return mObj->mData; }
00144     T*                  getData( const Vec2i &offset ) { return reinterpret_cast<T*>( reinterpret_cast<unsigned char*>( mObj->mData + offset.x * getPixelInc() ) + offset.y * mObj->mRowBytes ); }
00145     const T*            getData( const Vec2i &offset ) const { return reinterpret_cast<T*>( reinterpret_cast<unsigned char*>( mObj->mData + offset.x * getPixelInc() ) + offset.y * mObj->mRowBytes ); }
00146     T*                  getDataRed( const Vec2i &offset ) { return getData( offset ) + getRedOffset(); }
00147     const T*            getDataRed( const Vec2i &offset ) const { return getData( offset ) + getRedOffset(); }
00148     T*                  getDataGreen( const Vec2i &offset ) { return getData( offset ) + getGreenOffset(); }
00149     const T*            getDataGreen( const Vec2i &offset ) const { return getData( offset ) + getGreenOffset(); }
00150     T*                  getDataBlue( const Vec2i &offset ) { return getData( offset ) + getBlueOffset(); }
00151     const T*            getDataBlue( const Vec2i &offset ) const { return getData( offset ) + getBlueOffset(); }
00152     T*                  getDataAlpha( const Vec2i &offset ) { return getData( offset ) + getAlphaOffset(); }
00153     const T*            getDataAlpha( const Vec2i &offset ) const { return getData( offset ) + getAlphaOffset(); }
00154     
00155     void                setData( T *aData, int32_t aWidth, int32_t aHeight, int32_t aRowBytes );
00157     void                setDeallocator( void(*aDeallocatorFunc)( void * ), void *aDeallocatorRefcon );
00158     
00159     const SurfaceChannelOrder&  getChannelOrder() const { return mObj->mChannelOrder; }
00160     uint8_t                     getRedOffset() const { return mObj->mChannelOrder.getRedOffset(); }
00161     uint8_t                     getGreenOffset() const { return mObj->mChannelOrder.getGreenOffset(); }
00162     uint8_t                     getBlueOffset() const { return mObj->mChannelOrder.getBlueOffset(); }
00163     uint8_t                     getAlphaOffset() const { return mObj->mChannelOrder.getAlphaOffset(); }
00164     void                        setChannelOrder( const SurfaceChannelOrder &aChannelOrder );
00165 
00166     ChannelT<T>*                getChannel( uint8_t ChannelT ) { return &mObj->mChannels[ChannelT]; }
00167     ChannelT<T>*                getChannelRed() { return &mObj->mChannels[SurfaceChannelOrder::CHAN_RED]; }
00168     ChannelT<T>*                getChannelGreen() { return &mObj->mChannels[SurfaceChannelOrder::CHAN_GREEN]; }
00169     ChannelT<T>*                getChannelBlue() { return &mObj->mChannels[SurfaceChannelOrder::CHAN_BLUE]; }
00170     ChannelT<T>*                getChannelAlpha() { return &mObj->mChannels[SurfaceChannelOrder::CHAN_ALPHA]; }
00171 
00172     const ChannelT<T>*          getChannel( uint8_t ChannelT ) const { return &mObj->mChannels[ChannelT]; }
00173     const ChannelT<T>*          getChannelRed() const { return &mObj->mChannels[SurfaceChannelOrder::CHAN_RED]; }
00174     const ChannelT<T>*          getChannelGreen() const { return &mObj->mChannels[SurfaceChannelOrder::CHAN_GREEN]; }
00175     const ChannelT<T>*          getChannelBlue() const { return &mObj->mChannels[SurfaceChannelOrder::CHAN_BLUE]; }
00176     const ChannelT<T>*          getChannelAlpha() const { return &mObj->mChannels[SurfaceChannelOrder::CHAN_ALPHA]; }
00177 
00179     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() ); }
00181     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; }
00183     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; }
00184 
00185     void                copyFrom( const SurfaceT<T> &srcSurface, const Area &srcArea, const Vec2i &relativeOffset = Vec2i::zero() );
00186 //  template<typename T2>
00187 //  void                copy( const SurfaceT<T2> &srcSurface, const Area &srcArea, const Offset &dstOffset = Offset::zero() );  
00188 
00189     ColorT<T>                       areaAverage( const Area &area ) const;
00190 
00192 
00193     typedef shared_ptr<Obj> SurfaceT::*unspecified_bool_type;
00194     operator unspecified_bool_type() { return ( mObj.get() == 0 ) ? 0 : &SurfaceT::mObj; }
00195     void reset() { mObj.reset(); }
00197 
00198  private:
00199     shared_ptr<Obj>     mObj;
00200 
00201     void init( shared_ptr<class ImageSource> imageSource, const SurfaceConstraints &constraints = SurfaceConstraintsDefault(), boost::tribool alpha = boost::logic::indeterminate );
00202 
00203     void    copyRawSameChannelOrder( const SurfaceT<T> &srcSurface, const Area &srcArea, const Vec2i &absoluteOffset );
00204     void    copyRawRgba( const SurfaceT<T> &srcSurface, const Area &srcArea, const Vec2i &absoluteOffset );
00205     void    copyRawRgb( const SurfaceT<T> &srcSurface, const Area &srcArea, const Vec2i &absoluteOffset );
00206  
00207  public:
00208     class Iter {
00209      public:
00210         Iter( SurfaceT<T> &SurfaceT, const Area &area ) 
00211             : mRedOff( SurfaceT.getRedOffset() ), mGreenOff( SurfaceT.getGreenOffset() ), 
00212                 mBlueOff( SurfaceT.getBlueOffset() ), mAlphaOff( SurfaceT.getAlphaOffset() ),
00213                 mInc( SurfaceT.getPixelInc() ), mRowInc( SurfaceT.getRowBytes() )
00214         {
00215             Area clippedArea( area.getClipBy( SurfaceT.getBounds() ) );
00216             mWidth = clippedArea.getWidth();
00217             mHeight = clippedArea.getHeight();
00218             mLinePtr = reinterpret_cast<uint8_t*>( SurfaceT.getData( clippedArea.getUL() ) );
00219             mPtr = reinterpret_cast<T*>( mLinePtr );
00220             mStartX = mX = clippedArea.getX1();
00221             mStartY = mY = clippedArea.getY1();
00222             mEndX = clippedArea.getX2();
00223             mEndY = clippedArea.getY2();
00224             // in order to be at the right place after an initial call to line(), we need to back up one line
00225             mY = clippedArea.getY1() - 1;
00226             mLinePtr -= mRowInc;
00227         }
00228         
00229         T&          r() const { return mPtr[mRedOff]; }
00230         T&          g() const { return mPtr[mGreenOff]; }
00231         T&          b() const { return mPtr[mBlueOff]; }    
00232         T&          a() const { return mPtr[mAlphaOff]; }
00233 
00234         T&          r( int32_t xOff, int32_t yOff ) const { return mPtr[mRedOff + xOff * mInc + yOff * mRowInc]; }
00235         T&          g( int32_t xOff, int32_t yOff ) const { return mPtr[mGreenOff + xOff * mInc + yOff * mRowInc]; }
00236         T&          b( int32_t xOff, int32_t yOff ) const { return mPtr[mBlueOff + xOff * mInc + yOff * mRowInc]; } 
00237         T&          a( int32_t xOff, int32_t yOff ) const { return mPtr[mAlphaOff + xOff * mInc + yOff * mRowInc]; }
00238 
00239         T&          rClamped( int32_t xOff, int32_t yOff ) const
00240                         {   xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
00241                             return mPtr[mRedOff + xOff * mInc + yOff * mRowInc]; }
00242         T&          gClamped( int32_t xOff, int32_t yOff ) const
00243                         {   xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
00244                             return mPtr[mGreenOff + xOff * mInc + yOff * mRowInc]; }
00245         T&          bClamped( int32_t xOff, int32_t yOff ) const
00246                         {   xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
00247                             return mPtr[mBlueOff + xOff * mInc + yOff * mRowInc]; }     
00248         T&          aClamped( int32_t xOff, int32_t yOff ) const
00249                         {   xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
00250                             return mPtr[mAlphaOff + xOff * mInc + yOff * mRowInc]; }
00251         
00252         const int32_t   x() const { return mX; }
00253         const int32_t   y() const { return mY; }
00254         Vec2i           getPos() const { return Vec2i( mX, mY ); }
00255 
00256         bool pixel() {
00257             ++mX;
00258             mPtr += mInc;
00259             return mX < mEndX;
00260         }
00261         
00262         bool line() {
00263             ++mY;
00264             mLinePtr += mRowInc;
00265             mPtr = reinterpret_cast<T*>( mLinePtr );
00266             // in order to be at the right place after an initial call to pixel(), we need to back up one pixel
00267             mPtr -= mInc;
00268             mX = mStartX - 1;
00269             return mY < mEndY;
00270         }
00271         
00272         int32_t     getWidth() const { return mWidth; }
00273         int32_t     getHeight() const { return mHeight; }
00274 
00275         uint8_t             mRedOff, mGreenOff, mBlueOff, mAlphaOff, mInc;
00276         uint8_t             *mLinePtr;
00277         T                   *mPtr;
00278         int32_t             mRowInc, mWidth, mHeight;
00279         int32_t             mX, mY, mStartX, mStartY, mEndX, mEndY;
00280     };
00281 
00282     class ConstIter {
00283      public:
00284         ConstIter( const Iter &iter ) {
00285             mRedOff = iter.mRedOff;
00286             mGreenOff = iter.mGreenOff;
00287             mBlueOff = iter.mBlueOff;
00288             mAlphaOff = iter.mAlphaOff;
00289             mInc = iter.mInc;       
00290             mRowInc = iter.mRowInc;
00291             mWidth = iter.mWidth;
00292             mHeight = iter.mHeight;
00293             mLinePtr = iter.mLinePtr;
00294             mPtr = iter.mPtr;
00295             mStartX = iter.mStartX;
00296             mX = iter.mX;           
00297             mStartY = iter.mStartY;
00298             mY = iter.mY;
00299             mEndX = iter.mEndX;
00300             mEndY = iter.mEndY;
00301         }
00302         
00303         ConstIter( const SurfaceT<T> &SurfaceT, const Area &area ) 
00304             : mRedOff( SurfaceT.getRedOffset() ), mGreenOff( SurfaceT.getGreenOffset() ), 
00305                 mBlueOff( SurfaceT.getBlueOffset() ), mAlphaOff( SurfaceT.getAlphaOffset() ),
00306                 mInc( SurfaceT.getPixelInc() ), mRowInc( SurfaceT.getRowBytes() )
00307         {
00308             Area clippedArea( area.getClipBy( SurfaceT.getBounds() ) );
00309             mWidth = clippedArea.getWidth();
00310             mHeight = clippedArea.getHeight();
00311             mLinePtr = reinterpret_cast<const uint8_t*>( SurfaceT.getData( clippedArea.getUL() ) );
00312             mPtr = reinterpret_cast<const T*>( mLinePtr );
00313             mStartX = mX = clippedArea.getX1();
00314             mStartY = mY = clippedArea.getY1();
00315             mEndX = clippedArea.getX2();
00316             mEndY = clippedArea.getY2();
00317             // in order to be at the right place after an initial call to line(), we need to back up one line
00318             mY = clippedArea.getY1() - 1;
00319             mLinePtr -= mRowInc;
00320         }
00321         
00322         const T&    r() const { return mPtr[mRedOff]; }
00323         const T&    g() const { return mPtr[mGreenOff]; }
00324         const T&    b() const { return mPtr[mBlueOff]; }    
00325         const T&    a() const { return mPtr[mAlphaOff]; }
00326 
00327         const T&            r( int32_t xOff, int32_t yOff ) const { return mPtr[mRedOff + xOff * mInc + yOff * mRowInc]; }
00328         const T&            g( int32_t xOff, int32_t yOff ) const { return mPtr[mGreenOff + xOff * mInc + yOff * mRowInc]; }
00329         const T&            b( int32_t xOff, int32_t yOff ) const { return mPtr[mBlueOff + xOff * mInc + yOff * mRowInc]; } 
00330         const T&            a( int32_t xOff, int32_t yOff ) const { return mPtr[mAlphaOff + xOff * mInc + yOff * mRowInc]; }
00331 
00332         const T&    rClamped( int32_t xOff, int32_t yOff ) const
00333                         {   xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
00334                             return mPtr[mRedOff + xOff * mInc + yOff * mRowInc]; }
00335         const T&    gClamped( int32_t xOff, int32_t yOff ) const
00336                         {   xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
00337                             return mPtr[mGreenOff + xOff * mInc + yOff * mRowInc]; }
00338         const T&    bClamped( int32_t xOff, int32_t yOff ) const
00339                         {   xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
00340                             return mPtr[mBlueOff + xOff * mInc + yOff * mRowInc]; }     
00341         const T&    aClamped( int32_t xOff, int32_t yOff ) const
00342                         {   xOff = std::min(std::max(mX + xOff, mStartX),mEndX - 1) - mX; yOff = std::min(std::max( mY + yOff, mStartY ), mEndY - 1) - mY;
00343                             return mPtr[mAlphaOff + xOff * mInc + yOff * mRowInc]; }
00344         
00345         const int32_t   x() const { return mX; }
00346         const int32_t   y() const { return mY; }
00347         Vec2i           getPos() const { return Vec2i( mX, mY ); }
00348 
00349         bool pixel() {
00350             ++mX;
00351             mPtr += mInc;
00352             return mX < mEndX;
00353         }
00354         
00355         bool line() {
00356             ++mY;
00357             mLinePtr += mRowInc;
00358             mPtr = reinterpret_cast<const T*>( mLinePtr );
00359             // in order to be at the right place after an initial call to pixel(), we need to back up one pixel
00360             mPtr -= mInc;
00361             mX = mStartX - 1;
00362             return mY < mEndY;
00363         }
00364         
00365         int32_t     getWidth() const { return mWidth; }
00366         int32_t     getHeight() const { return mHeight; }
00367 
00368         uint8_t             mRedOff, mGreenOff, mBlueOff, mAlphaOff, mInc;
00369         const uint8_t       *mLinePtr;
00370         const T             *mPtr;
00371         int32_t             mRowInc, mWidth, mHeight;
00372         int32_t             mX, mY, mStartX, mStartY, mEndX, mEndY;
00373     };
00374 
00375     Iter        getIter() { return Iter( *this, this->getBounds() ); }
00376     Iter        getIter( const Area &area ) { return Iter( *this, area ); }
00377     ConstIter   getIter() const { return ConstIter( *this, this->getBounds() ); }
00378     ConstIter   getIter( const Area &area ) const { return ConstIter( *this, area ); }
00379 };
00380 
00381 class SurfaceExc : public std::exception {
00382     virtual const char* what() const throw() {
00383         return "Surface exception";
00384     }
00385 };
00386 
00387 class SurfaceConstraintsExc : public SurfaceExc {
00388     virtual const char* what() const throw() {
00389         return "Surface exception: does not conform to expected SurfaceConstraints";
00390     }
00391 };
00392 
00393 typedef SurfaceT<uint8_t> Surface;
00394 typedef SurfaceT<uint8_t> Surface8u;
00395 typedef SurfaceT<float> Surface32f;
00396 
00397 } // namespace cinder