TuttleOFX  1
ImageMagickReaderProcess.tcc
Go to the documentation of this file.
00001 #include "ImageMagickReaderDefinitions.hpp"
00002 #include "ImageMagickReaderProcess.hpp"
00003 
00004 #include <tuttle/common/system/system.hpp>
00005 #include <terry/globals.hpp>
00006 #include <tuttle/plugin/exceptions.hpp>
00007 
00008 #include <magick/MagickCore.h>
00009 
00010 #include <boost/gil/gil_all.hpp>
00011 #include <boost/filesystem/fstream.hpp>
00012 #include <boost/scoped_ptr.hpp>
00013 #include <boost/lexical_cast.hpp>
00014 #include <boost/assert.hpp>
00015 
00016 
00017 #if ( MAGICKCORE_QUANTUM_DEPTH == 8 )
00018  #ifdef _MSC_VER
00019   #pragma NOTE( "MAGICKCORE_QUANTUM_DEPTH is 8" )
00020  #else
00021   #warning "MAGICKCORE_QUANTUM_DEPTH is 8"
00022  #endif
00023  #define MAGICKCORE_QUANTUM_SUPPORT boost::uint32_t
00024 #elif ( MAGICKCORE_QUANTUM_DEPTH == 16 )
00025  #ifdef _MSC_VER
00026   #pragma NOTE( "MAGICKCORE_QUANTUM_DEPTH is 16" )
00027  #else
00028   #warning "MAGICKCORE_QUANTUM_DEPTH is 16"
00029  #endif
00030  #define MAGICKCORE_QUANTUM_SUPPORT boost::uint64_t
00031 #elif ( MAGICKCORE_QUANTUM_DEPTH == 32 )
00032  #ifdef _MSC_VER
00033   #pragma NOTE( "MAGICKCORE_QUANTUM_DEPTH is 32" )
00034  #else
00035   #warning "MAGICKCORE_QUANTUM_DEPTH is 32"
00036   #define MAGICKCORE_QUANTUM_SUPPORT boost::uint64_t
00037  #endif
00038 #endif
00039 
00040 BOOST_STATIC_ASSERT( MAGICKCORE_QUANTUM_DEPTH != 8 || MAGICKCORE_QUANTUM_DEPTH != 16 );
00041 
00042 namespace boost {
00043 namespace gil  {
00044 
00045 typedef const packed_channel_reference<MAGICKCORE_QUANTUM_SUPPORT, MAGICKCORE_QUANTUM_DEPTH*0, MAGICKCORE_QUANTUM_DEPTH, true> rgba_quantum_packed_channel0_t;
00046 typedef const packed_channel_reference<MAGICKCORE_QUANTUM_SUPPORT, MAGICKCORE_QUANTUM_DEPTH*1, MAGICKCORE_QUANTUM_DEPTH, true> rgba_quantum_packed_channel1_t;
00047 typedef const packed_channel_reference<MAGICKCORE_QUANTUM_SUPPORT, MAGICKCORE_QUANTUM_DEPTH*2, MAGICKCORE_QUANTUM_DEPTH, true> rgba_quantum_packed_channel2_t;
00048 typedef const packed_channel_reference<MAGICKCORE_QUANTUM_SUPPORT, MAGICKCORE_QUANTUM_DEPTH*3, MAGICKCORE_QUANTUM_DEPTH, true> rgba_quantum_packed_channel3_t;
00049 
00050 typedef const packed_channel_reference<MAGICKCORE_QUANTUM_SUPPORT, MAGICKCORE_QUANTUM_DEPTH*0, MAGICKCORE_QUANTUM_DEPTH, true> rgb_quantum_packed_channel0_t;
00051 typedef const packed_channel_reference<MAGICKCORE_QUANTUM_SUPPORT, MAGICKCORE_QUANTUM_DEPTH*1, MAGICKCORE_QUANTUM_DEPTH, true> rgb_quantum_packed_channel1_t;
00052 typedef const packed_channel_reference<MAGICKCORE_QUANTUM_SUPPORT, MAGICKCORE_QUANTUM_DEPTH*2, MAGICKCORE_QUANTUM_DEPTH, true> rgb_quantum_packed_channel2_t;
00053 
00054 // RGBA
00055 typedef mpl::vector4<rgba_quantum_packed_channel0_t, rgba_quantum_packed_channel1_t,
00056 rgba_quantum_packed_channel2_t, rgba_quantum_packed_channel3_t> rgba_quantum_packed_channels_t;
00057 typedef packed_pixel<MAGICKCORE_QUANTUM_SUPPORT, rgba_quantum_packed_channels_t, bgra_layout_t> bgra_quantum_packed_pixel_t;
00058 typedef view_type_from_pixel<bgra_quantum_packed_pixel_t>::type bgra_quantum_packed_view_t;
00059 typedef image<bgra_quantum_packed_pixel_t, false> bgra_quantum_packed_image_t;
00060 
00061 // RGB
00062 typedef mpl::vector3<rgb_quantum_packed_channel0_t, rgb_quantum_packed_channel1_t,
00063 rgb_quantum_packed_channel2_t> rgb_quantum_packed_channels_t;
00064 typedef packed_pixel<MAGICKCORE_QUANTUM_SUPPORT, rgb_quantum_packed_channels_t, bgr_layout_t> bgr_quantum_packed_pixel_t;
00065 typedef view_type_from_pixel<bgr_quantum_packed_pixel_t>::type bgr_quantum_packed_view_t;
00066 typedef image<bgr_quantum_packed_pixel_t, false> bgr_quantum_packed_image_t;
00067 
00068 }
00069 }
00070 
00071 namespace tuttle {
00072 namespace plugin {
00073 namespace imagemagick {
00074 namespace reader {
00075 
00076 using namespace boost::gil;
00077 namespace bfs = boost::filesystem;
00078 
00079 template<class View>
00080 ImageMagickReaderProcess<View>::ImageMagickReaderProcess( ImageMagickReaderPlugin& instance )
00081         : ImageGilProcessor<View>( instance, eImageOrientationFromTopToBottom )
00082         , _plugin( instance )
00083 {
00084         this->setNoMultiThreading();
00085 }
00086 
00087 template<class View>
00088 void ImageMagickReaderProcess<View>::setup( const OFX::RenderArguments& args )
00089 {
00090         ImageGilProcessor<View>::setup( args );
00091         _params = _plugin.getProcessParams( args.time );
00092 }
00093 
00094 /**
00095  * @brief Function called by rendering thread each time a process must be done.
00096  * @param[in] procWindowRoW  Processing window in RoW
00097  */
00098 template<class View>
00099 void ImageMagickReaderProcess<View>::multiThreadProcessImages( const OfxRectI& procWindowRoW )
00100 {
00101         // no tiles and no multithreading supported
00102         BOOST_ASSERT( procWindowRoW == this->_dstPixelRod );
00103         readGilImage( this->_dstView, _plugin.getProcessParams( this->_renderArgs.time )._filepath );
00104 }
00105 
00106 template<class SView, class DView>
00107 void copy_and_convert_from_buffer( Image* image, DView& dst )
00108 {
00109         ExceptionInfo exception;
00110         PixelPacket* buffer =  GetAuthenticPixels( image, 0, 0, dst.width(), dst.height(), &exception );
00111         
00112         SView bufferView = interleaved_view( dst.width(), dst.height(),
00113                                                                                  ( typename SView::value_type* )( buffer ),
00114                                                                                  dst.width() * sizeof( typename SView::value_type ) );
00115         
00116         boost::gil::copy_and_convert_pixels( bufferView, dst );
00117 }
00118 
00119 /**
00120  */
00121 template<class View>
00122 View& ImageMagickReaderProcess<View>::readGilImage( View& dst, const std::string& filepath )
00123 {
00124         ImageInfo* imageInfo = AcquireImageInfo();
00125         GetImageInfo( imageInfo );
00126         strcpy( imageInfo->filename, filepath.c_str() );
00127         ExceptionInfo* exceptionsInfo = AcquireExceptionInfo();
00128         GetExceptionInfo( exceptionsInfo );
00129         
00130         ::Image* image = ReadImage( imageInfo, exceptionsInfo );
00131         
00132         CatchException( exceptionsInfo );
00133         
00134         if( image->colorspace != RGBColorspace &&
00135                         image->colorspace != GRAYColorspace &&
00136                         image->colorspace != TransparentColorspace )
00137         {
00138                 TUTTLE_LOG_WARNING( " Change colorspace to RGB." );
00139                 SetImageColorspace( image, RGBColorspace );
00140         }
00141         
00142         QuantumType colorType = GetQuantumType( image, exceptionsInfo );
00143         
00144         switch( colorType )
00145         {
00146                 case RGBQuantum:
00147                 {
00148 #if ( MAGICKCORE_QUANTUM_DEPTH == 8 )
00149                         rgb8_image_t tmpImg ( dst.width(), dst.height() );
00150                         rgb8_view_t tmpVw = view( tmpImg );
00151                         
00152                         copy_and_convert_from_buffer<bgr_quantum_packed_view_t, rgb8_view_t>( image, tmpVw );
00153 #elif ( MAGICKCORE_QUANTUM_DEPTH == 16 )
00154                         rgb16_image_t tmpImg ( dst.width(), dst.height() );
00155                         rgb16_view_t tmpVw = view( tmpImg );
00156                         
00157                         copy_and_convert_from_buffer<bgr_quantum_packed_view_t, rgb16_view_t>( image, tmpVw );
00158 #elif ( MAGICKCORE_QUANTUM_DEPTH == 32 )
00159                         rgb32_image_t tmpImg ( dst.width(), dst.height() );
00160                         rgb32_view_t tmpVw = view( tmpImg );
00161                         
00162                         copy_and_convert_from_buffer<bgr_quantum_packed_view_t, rgb32_view_t>( image, tmpVw );
00163 #endif
00164                         copy_and_convert_pixels( tmpVw, dst );
00165                         break;
00166                 }
00167                 case RGBAQuantum:
00168                 {
00169 #if ( MAGICKCORE_QUANTUM_DEPTH == 8 )
00170                         copy_and_convert_from_buffer<bgra8_view_t, View>( image, dst );
00171 #elif ( MAGICKCORE_QUANTUM_DEPTH == 16 )
00172                         copy_and_convert_from_buffer<bgra16_view_t, View>( image, dst );
00173 #elif ( MAGICKCORE_QUANTUM_DEPTH == 32 )
00174                         copy_and_convert_from_buffer<bgra32_view_t, View>( image, dst );
00175 #endif
00176                         break;
00177                 }
00178                 case AlphaQuantum:
00179                 case GrayQuantum:
00180                 {
00181                         
00182 #if ( MAGICKCORE_QUANTUM_DEPTH == 8 )
00183                         rgba8_image_t tmpImg ( dst.width(), dst.height() );
00184                         rgba8_view_t tmpVw = view( tmpImg );
00185                         
00186                         copy_and_convert_from_buffer<bgra_quantum_packed_view_t, rgba8_view_t>( image, tmpVw );
00187 #elif ( MAGICKCORE_QUANTUM_DEPTH == 16 )
00188                         rgba16_image_t tmpImg ( dst.width(), dst.height() );
00189                         rgba16_view_t tmpVw = view( tmpImg );
00190                         
00191                         copy_and_convert_from_buffer<bgra_quantum_packed_view_t, rgba16_view_t>( image, tmpVw );
00192 #elif ( MAGICKCORE_QUANTUM_DEPTH == 32 )
00193                         rgba32_image_t tmpImg ( dst.width(), dst.height() );
00194                         rgba32_view_t tmpVw = view( tmpImg );
00195                         
00196                         copy_and_convert_from_buffer<bgra_quantum_packed_view_t, rgba32_view_t>( image, tmpVw );
00197 #endif
00198                         copy_and_convert_pixels( boost::gil::nth_channel_view ( tmpVw, 0 ), dst );
00199                         
00200                         break;
00201                 }
00202                 default:
00203                 {
00204                         BOOST_THROW_EXCEPTION( exception::Unsupported()
00205                                                                    << exception::user( "Unknown color type (" + boost::lexical_cast<std::string>( colorType )+")" ) );
00206                         break;
00207                 }
00208         }
00209         
00210         image          = DestroyImage( image );
00211         imageInfo      = DestroyImageInfo( imageInfo );
00212         exceptionsInfo = DestroyExceptionInfo( exceptionsInfo );
00213         return dst;
00214 }
00215 
00216 }
00217 }
00218 }
00219 }