include/cinder/ImageIo.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/DataSource.h"
00027 #include "cinder/DataTarget.h"
00028 #include "cinder/Surface.h"
00029 #include "cinder/Exception.h"
00030 
00031 #include <vector>
00032 #include <map>
00033 #include <utility>
00034 
00035 namespace cinder {
00036 
00037 typedef std::shared_ptr<class ImageSource>      ImageSourceRef;
00038 typedef std::shared_ptr<class ImageLoader>      ImageLoaderRef;
00039 typedef std::shared_ptr<class ImageTarget>      ImageTargetRef;
00040 typedef std::shared_ptr<class ImageTargetFile>  ImageTargetFileRef;
00041 
00042 class ImageIo {
00043   public:
00044     typedef enum ColorModel { CM_RGB, CM_GRAY, CM_UNKNOWN } ColorModel;
00045     typedef enum DataType { UINT8, UINT16, FLOAT32, DATA_UNKNOWN } DataType;
00046     typedef enum ChannelType { CHAN_RGB_R, CHAN_RGB_G, CHAN_RGB_B, CHAN_GRAY, CHAN_ALPHA, CHAN_MASK, CHAN_LAB_L, CHAN_LAB_A, CHAN_LAB_B,
00047                     CHAN_YUV_Y, CHAN_YUV_U, CHAN_YUV_V, CHAN_CMYK_C, CHAN_CMYK_M, CHAN_CMYK_Y, CHAN_CMYK_K,
00048                     CHAN_UNKNOWN } ChannelType;
00049     typedef enum ChannelOrder { RGBA, BGRA, ARGB, ABGR, RGBX, BGRX, XRGB, XBGR, RGB, BGR, Y, YA, CUSTOM } ChannelOrder;     // Y = Gray/Luminance, X = ignored
00050 
00051     int32_t         getWidth() const { return mWidth; }
00052     int32_t         getHeight() const { return mHeight; }
00053     ColorModel      getColorModel() const { return mColorModel; }
00054     DataType        getDataType() const { return mDataType; }
00055     ChannelOrder    getChannelOrder() const { return mChannelOrder; }
00056     virtual bool    hasAlpha() const { return channelOrderHasAlpha( mChannelOrder ); }
00057 
00058     static void     translateRgbColorModelToOffsets( ChannelOrder channelOrder, int8_t *red, int8_t *green, int8_t *blue, int8_t *alpha, int8_t *inc );
00059     static void     translateGrayColorModelToOffsets( ChannelOrder channelOrder, int8_t *gray, int8_t *alpha, int8_t *inc );
00060     static bool     channelOrderHasAlpha( ChannelOrder channelOrder );
00061     static int8_t   channelOrderNumChannels( ChannelOrder channelOrder );
00062     static uint8_t  dataTypeBytes( DataType dataType );
00063 
00065     static std::vector<std::string> getLoadExtensions();
00067     static std::vector<std::string> getWriteExtensions();
00068 
00069   protected:
00070     ImageIo();
00071 
00072     void    setSize( int32_t width, int32_t height ) { mWidth = width; mHeight = height; }
00073     void    setColorModel( ColorModel colorModel ) { mColorModel  = colorModel; }
00074     void    setDataType( DataType aDataType ) { mDataType = aDataType; }    
00075     void    setChannelOrder( ChannelOrder aChannelOrder ) { mChannelOrder = aChannelOrder; }
00076 
00077     int32_t                     mWidth, mHeight;
00078     ColorModel                  mColorModel;
00079     DataType                    mDataType;
00080     ChannelOrder                mChannelOrder;
00081 };
00082 
00083 class ImageSource : public ImageIo {
00084   public:
00085     ImageSource() : ImageIo(), mIsPremultiplied( false ), mPixelAspectRatio( 1 ), mCustomPixelInc( 0 ) {}
00086     virtual ~ImageSource() {}  
00087 
00088     class Options {
00089       public:
00090         Options() : mIndex( 0 ) {}
00091 
00093         Options& index( int32_t aIndex ) { mIndex = aIndex; return *this; }
00094         
00095         int32_t             getIndex() const { return mIndex; }
00096         
00097       protected:
00098         int32_t         mIndex;
00099     };
00100 
00102     float       getPixelAspectRatio() const;
00104     bool        isPremultiplied() const;
00105 
00106     virtual void    load( ImageTargetRef target ) = 0;
00107 
00108     typedef void (ImageSource::*RowFunc)(ImageTargetRef, int32_t, const void*);
00109 
00110   protected:
00111     void        setPixelAspectRatio( float pixelAspectRatio ) { mPixelAspectRatio = pixelAspectRatio; }
00112     void        setPremultiplied( bool premult = true ) { mIsPremultiplied = premult; }
00114     void        setCustomPixelInc( int8_t customPixelInc ) { mCustomPixelInc = customPixelInc; }
00115 
00116     RowFunc     setupRowFunc( ImageTargetRef target );
00117     void        setupRowFuncRgbSource( ImageTargetRef target );
00118     void        setupRowFuncGraySource( ImageTargetRef target );
00119     template<typename SD, typename TD, ColorModel TCS>
00120     RowFunc     setupRowFuncForTypesAndTargetColorModel( ImageTargetRef target );
00121     template<typename SD, typename TD>
00122     RowFunc     setupRowFuncForTypes( ImageTargetRef target );
00123     template<typename SD>
00124     RowFunc     setupRowFuncForSourceType( ImageTargetRef target );
00125 
00126     template<typename SD, typename TD, ImageIo::ColorModel TCM, bool ALPHA>
00127     void        rowFuncSourceRgb( ImageTargetRef target, int32_t row, const void *data );
00128     template<typename SD, typename TD, ColorModel TCM, bool ALPHA>
00129     void        rowFuncSourceGray( ImageTargetRef target, int32_t row, const void *data );
00130 
00131     float                       mPixelAspectRatio;
00132     bool                        mIsPremultiplied;
00133     int8_t                      mCustomPixelInc;
00134     
00135     int8_t                      mRowFuncSourceRed, mRowFuncSourceGreen, mRowFuncSourceBlue, mRowFuncSourceAlpha;
00136     int8_t                      mRowFuncTargetRed, mRowFuncTargetGreen, mRowFuncTargetBlue, mRowFuncTargetAlpha;
00137     int8_t                      mRowFuncSourceGray, mRowFuncTargetGray;
00138     int8_t                      mRowFuncSourceInc, mRowFuncTargetInc;
00139 };
00140 
00141 class ImageTarget : public ImageIo {
00142   public:
00143     virtual ~ImageTarget() {};
00144 
00145     virtual void*   getRowPointer( int32_t row ) = 0;
00146     virtual void    setRow( int32_t row, const void *data ) { throw; }
00147     virtual void    finalize() { }
00148     
00149     class Options {
00150       public:
00151         Options() : mQuality( 0.9f ), mColorModelDefault( true ) {}
00152         
00153         Options& quality( float quality ) { mQuality = quality; return *this; }
00154         Options& colorModel( ImageIo::ColorModel cm ) { mColorModelDefault = false; mColorModel = cm; return *this; }
00155         
00156         void    setColorModelDefault() { mColorModelDefault = true; }
00157         
00158         float               getQuality() const { return mQuality; }
00159         bool                isColorModelDefault() const { return mColorModelDefault; }
00160         ImageIo::ColorModel getColorModel() const { return mColorModel; }
00161         
00162       protected:
00163         float                   mQuality;
00164         bool                    mColorModelDefault;
00165         ImageIo::ColorModel     mColorModel;
00166     };
00167     
00168   protected:
00169     ImageTarget() {}    
00170 };
00171 
00173 ImageSourceRef  loadImage( const fs::path &path, ImageSource::Options options = ImageSource::Options(), std::string extension = "" );
00175 ImageSourceRef  loadImage( DataSourceRef dataSource, ImageSource::Options options = ImageSource::Options(), std::string extension = "" );
00177 void            writeImage( DataTargetRef dataTarget, const ImageSourceRef &imageSource, ImageTarget::Options options = ImageTarget::Options(), std::string extension = "" );
00180 void            writeImage( const fs::path &path, const ImageSourceRef &imageSource, ImageTarget::Options options = ImageTarget::Options(), std::string extension = "" );
00182 void            writeImage( ImageTargetRef imageTarget, const ImageSourceRef &imageSource );
00183 
00184 class ImageIoException : public Exception {
00185 };
00186 
00187 class ImageIoExceptionFailedLoad : public ImageIoException {
00188 };
00189 
00190 class ImageIoExceptionFailedWrite : public ImageIoException {
00191 };
00192 
00193 class ImageIoExceptionUnknownExtension : public ImageIoException {
00194 };
00195 
00196 class ImageIoExceptionIllegalColorModel : public ImageIoException {
00197 };
00198 
00199 class ImageIoExceptionIllegalDataType : public ImageIoException {
00200 };
00201 
00202 class ImageIoExceptionIllegalChannelOrder : public ImageIoException {
00203 };
00204 
00205 
00206 struct ImageIoRegistrar {
00207     typedef ImageSourceRef (*SourceCreationFunc)( DataSourceRef, ImageSource::Options options );
00208     typedef ImageTargetRef (*TargetCreationFunc)( DataTargetRef, ImageSourceRef, ImageTarget::Options options, const std::string& );
00209 
00210     static ImageSourceRef   createSource( DataSourceRef dataSource, ImageSource::Options options, std::string extension );
00211     static ImageTargetRef   createTarget( DataTargetRef dataTarget, ImageSourceRef imageSource, ImageTarget::Options options, std::string extension );
00212     
00213     static void     registerSourceType( std::string extension, SourceCreationFunc func, int32_t priority = 2 );
00214     static void     registerSourceGeneric( SourceCreationFunc func, int32_t priority = 2 );
00215     
00216     static void     registerTargetType( std::string extension, TargetCreationFunc func, int32_t priority, const std::string &extensionData );
00217     
00218   private:
00219     
00220     struct Inst {
00221         void    registerSourceType( std::string extension, SourceCreationFunc func, int32_t priority );
00222         void    registerSourceGeneric( SourceCreationFunc func, int32_t priority );
00223         void    registerTargetType( std::string extension, TargetCreationFunc func, int32_t priority, const std::string &extensionData );       
00224 
00225         ImageSourceRef  createSource( DataSourceRef dataSource, ImageSource::Options options, std::string extension );
00226         ImageTargetRef  createTarget( DataTargetRef dataTarget, ImageSourceRef imageSource, ImageTarget::Options options, std::string extension );
00227     
00228         std::map<std::string, std::multimap<int32_t,SourceCreationFunc> >   mSources;
00229         std::map<int32_t, SourceCreationFunc>                               mGenericSources;
00230         std::map<std::string, std::multimap<int32_t,std::pair<TargetCreationFunc,std::string> > >   mTargets;
00231     };
00232 
00233     static ImageIoRegistrar::Inst*  instance();     
00234         
00235     friend class ImageIo;
00236 };
00237 
00238 template<typename T>
00239 struct ImageIoRegistrant {
00240     ImageIoRegistrant() {
00241         (void) register_object;
00242     }
00243   private:
00244     struct exec_register {
00245         exec_register() {
00246             T::registerSelf();
00247         }
00248     };
00249     
00250     static exec_register register_object;
00251 };
00252 
00253 template<typename D> typename ImageIoRegistrant<D>::exec_register ImageIoRegistrant<D>::register_object;
00254 
00255 #define REGISTER_IMAGE_IO_FILE_HANDLER( TYPE ) \
00256 struct ImageIoRegisterT##TYPE : public ImageIoRegistrant<TYPE> { \
00257     ImageIoRegisterT##TYPE() : ImageIoRegistrant<TYPE>() {} \
00258 };
00259 
00260 } // namespace cinder