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    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