TuttleOFX  1
Image.cpp
Go to the documentation of this file.
00001 #include "Image.hpp"
00002 #include <tuttle/host/attribute/ClipImage.hpp>
00003 #include <tuttle/host/Core.hpp>
00004 
00005 #include <tuttle/common/utils/global.hpp>
00006 
00007 #include <boost/gil/image.hpp>
00008 #include <boost/gil/image_view.hpp>
00009 #include <boost/gil/typedefs.hpp>
00010 
00011 #ifndef TUTTLE_PRODUCTION
00012 #ifdef TUTTLE_PNG_EXPORT_BETWEEN_NODES
00013 #define int_p_NULL (int *)NULL
00014  #include <boost/gil/extension/io/png_io.hpp>
00015 #endif
00016 #endif
00017 
00018 namespace tuttle {
00019 namespace host {
00020 namespace attribute {
00021 
00022 Image::Image( ClipImage& clip, const OfxTime time, const OfxRectD& bounds, const EImageOrientation orientation, const int rowDistanceBytes )
00023         : ofx::imageEffect::OfxhImage( clip, time ) ///< this ctor will set basic props on the image
00024         , _memorySize( 0 )
00025         , _pixelBytes( clip.getPixelMemorySize() )
00026         , _rowAbsDistanceBytes( 0 )
00027         , _orientation( orientation )
00028         , _fullname( clip.getFullName() )
00029 {
00030         // Set rod in canonical & pixel coord.
00031         const double par = clip.getPixelAspectRatio();
00032         _bounds.x1 = std::floor(bounds.x1 / par);
00033         _bounds.x2 = std::ceil(bounds.x2 / par);
00034         _bounds.y1 = std::floor(bounds.y1);
00035         _bounds.y2 = std::ceil(bounds.y2);
00036 
00037         const OfxPointI dimensions = { _bounds.x2 - _bounds.x1, _bounds.y2 - _bounds.y1 };
00038 
00039         // make some memory according to the bit depth
00040         const std::size_t automaticRowSize = dimensions.x * _pixelBytes;
00041         _memorySize = automaticRowSize * dimensions.y;
00042 
00043         // render scale x and y of 1.0
00044         setDoubleProperty( kOfxImageEffectPropRenderScale, 1.0, 0 );
00045         setDoubleProperty( kOfxImageEffectPropRenderScale, 1.0, 1 );
00046 
00047         // bounds and rod
00048         setIntProperty( kOfxImagePropBounds, _bounds.x1, 0 );
00049         setIntProperty( kOfxImagePropBounds, _bounds.y1, 1 );
00050         setIntProperty( kOfxImagePropBounds, _bounds.x2, 2 );
00051         setIntProperty( kOfxImagePropBounds, _bounds.y2, 3 );
00052 
00053         /// @todo the same for bounds and rod, no tiles for the moment !
00054         setIntProperty( kOfxImagePropRegionOfDefinition, _bounds.x1, 0 );
00055         setIntProperty( kOfxImagePropRegionOfDefinition, _bounds.y1, 1 );
00056         setIntProperty( kOfxImagePropRegionOfDefinition, _bounds.x2, 2 );
00057         setIntProperty( kOfxImagePropRegionOfDefinition, _bounds.y2, 3 );
00058 
00059         // row bytes
00060         _rowAbsDistanceBytes = rowDistanceBytes != 0 ? rowDistanceBytes : automaticRowSize;
00061         setIntProperty( kOfxImagePropRowBytes, getOrientedRowDistanceBytes( eImageOrientationFromBottomToTop ) );
00062 }
00063 
00064 Image::~Image()
00065 {
00066         //TUTTLE_TLOG_VAR( TUTTLE_TRACE, getFullName() );
00067 }
00068 
00069 boost::uint8_t* Image::getPixelData()
00070 {
00071         return reinterpret_cast<boost::uint8_t*>( _data->data() );
00072 }
00073 
00074 void* Image::getVoidPixelData()
00075 {
00076         return reinterpret_cast<void*>( _data->data() );
00077 }
00078 
00079 char* Image::getCharPixelData()
00080 {
00081         return reinterpret_cast<char*>( _data->data() );
00082 }
00083 
00084 boost::uint8_t* Image::getOrientedPixelData( const EImageOrientation orientation )
00085 {
00086         if( _orientation == orientation )
00087         {
00088                 return getPixelData();
00089         }
00090         else
00091         {
00092                 const std::ssize_t distance = getRowAbsDistanceBytes() * (_bounds.y2 - _bounds.y1 - 1);
00093                 return reinterpret_cast<boost::uint8_t*>( getPixelData() + distance );
00094         }
00095 }
00096 
00097 
00098 boost::uint8_t* Image::pixel( const int x, const int y )
00099 {
00100         const OfxRectI bounds = getBounds();
00101 
00102         if( ( x >= bounds.x1 ) && ( x < bounds.x2 ) && ( y >= bounds.y1 ) && ( y < bounds.y2 ) )
00103         {
00104                 const int yOffset = ( _orientation == eImageOrientationFromTopToBottom ) ? ( y - bounds.y1 ) : ( y - bounds.y2 );
00105                 const int offset = yOffset * getRowAbsDistanceBytes() + ( x - bounds.x1 ) * _pixelBytes;
00106                 return reinterpret_cast<boost::uint8_t*>( getPixelData() + offset );
00107         }
00108         return NULL;
00109 }
00110 
00111 template < class D_VIEW, class S_VIEW >
00112 void Image::copy( D_VIEW& dst, S_VIEW& src, const OfxPointI& dstCorner,
00113                   const OfxPointI& srcCorner, const OfxPointI& count )
00114 {
00115         using namespace boost::gil;
00116         if( src.width() >= ( count.x - srcCorner.x ) &&
00117             src.height() >= ( count.y - srcCorner.y ) &&
00118             dst.width() >= ( count.x - dstCorner.x ) &&
00119             dst.height() >= ( count.y - dstCorner.y ) )
00120         {
00121                 S_VIEW subSrc = subimage_view( src, srcCorner.x, srcCorner.y, count.x, count.y );
00122                 D_VIEW subDst = subimage_view( dst, dstCorner.x, dstCorner.y, count.x, count.y );
00123                 copy_and_convert_pixels( subSrc, subDst );
00124         }
00125 }
00126 
00127 #ifndef TUTTLE_PRODUCTION
00128 #ifdef TUTTLE_PNG_EXPORT_BETWEEN_NODES
00129 void Image::debugSaveAsPng( const std::string& filename )
00130 {
00131         using namespace boost::gil;
00132         switch( getComponentsType() )
00133         {
00134                 case ofx::imageEffect::ePixelComponentRGBA:
00135                         switch( getBitDepth() )
00136                         {
00137                                 case ofx::imageEffect::eBitDepthUByte:
00138                                 {
00139                                         rgba8_view_t view = getGilView<rgba8_view_t >();
00140                                         png_write_view( filename, view );
00141                                         break;
00142                                 }
00143                                 case ofx::imageEffect::eBitDepthUShort:
00144                                 {
00145                                         rgba16_view_t view = getGilView<rgba16_view_t >();
00146                                         png_write_view( filename, view );
00147                                         break;
00148                                 }
00149                                 case ofx::imageEffect::eBitDepthFloat:
00150                                 {
00151                                         rgba32f_view_t view = getGilView<rgba32f_view_t >();
00152                                         png_write_view( filename, color_converted_view<rgba8_pixel_t>( view ) );
00153                                         break;
00154                                 }
00155                                 default:
00156                                         break;
00157                         }
00158                         break;
00159                 case ofx::imageEffect::ePixelComponentAlpha:
00160                         switch( getBitDepth() )
00161                         {
00162                                 case ofx::imageEffect::eBitDepthUByte:
00163                                 {
00164                                         gray8_view_t view = getGilView<gray8_view_t >();
00165                                         png_write_view( filename, view );
00166                                         break;
00167                                 }
00168                                 case ofx::imageEffect::eBitDepthUShort:
00169                                 {
00170                                         gray16_view_t view = getGilView<gray16_view_t >();
00171                                         png_write_view( filename, view );
00172                                         break;
00173                                 }
00174                                 case ofx::imageEffect::eBitDepthFloat:
00175                                 {
00176                                         gray32f_view_t view = getGilView<gray32f_view_t >();
00177                                         png_write_view( filename, color_converted_view<rgb8_pixel_t>( view ) );
00178                                         break;
00179                                 }
00180                                 default:
00181                                         break;
00182                         }
00183                         break;
00184                 default:
00185                         break;
00186         }
00187 }
00188 #endif
00189 #endif
00190 
00191 /// Copy from gil image view to Image
00192 template < class S_VIEW >
00193 void Image::copy( Image* dst, S_VIEW& src, const OfxPointI& dstCorner,
00194                   const OfxPointI& srcCorner, const OfxPointI& count )
00195 {
00196         using namespace boost::gil;
00197         // Create destination
00198         switch( dst->getComponentsType() )
00199         {
00200                 case ofx::imageEffect::ePixelComponentRGBA:
00201                         switch( dst->getBitDepth() )
00202                         {
00203                                 case ofx::imageEffect::eBitDepthUByte:
00204                                 {
00205                                         rgba8_view_t dView = dst->getGilView<rgba8_view_t >();
00206                                         Image::copy( dView, src, dstCorner, srcCorner, count );
00207                                         break;
00208                                 }
00209                                 case ofx::imageEffect::eBitDepthUShort:
00210                                 {
00211                                         rgba16_view_t dView = dst->getGilView<rgba16_view_t >();
00212                                         Image::copy( dView, src, dstCorner, srcCorner, count );
00213                                         break;
00214                                 }
00215                                 case ofx::imageEffect::eBitDepthFloat:
00216                                 {
00217                                         rgba32f_view_t dView = dst->getGilView<rgba32f_view_t >();
00218                                         Image::copy( dView, src, dstCorner, srcCorner, count );
00219                                         break;
00220                                 }
00221                                 default:
00222                                         break;
00223                         }
00224                         break;
00225                 case ofx::imageEffect::ePixelComponentAlpha:
00226                         switch( dst->getBitDepth() )
00227                         {
00228                                 case ofx::imageEffect::eBitDepthUByte:
00229                                 {
00230                                         gray8_view_t dView = dst->getGilView<gray8_view_t >();
00231                                         Image::copy( dView, src, dstCorner, srcCorner, count );
00232                                         break;
00233                                 }
00234                                 case ofx::imageEffect::eBitDepthUShort:
00235                                 {
00236                                         gray16_view_t dView = dst->getGilView<gray16_view_t >();
00237                                         Image::copy( dView, src, dstCorner, srcCorner, count );
00238                                         break;
00239                                 }
00240                                 case ofx::imageEffect::eBitDepthFloat:
00241                                 {
00242                                         gray32f_view_t dView = dst->getGilView<gray32f_view_t >();
00243                                         Image::copy( dView, src, dstCorner, srcCorner, count );
00244                                         break;
00245                                 }
00246                                 default:
00247                                         break;
00248                         }
00249                         break;
00250                 default:
00251                         break;
00252         }
00253 }
00254 
00255 /// Copy from Image to Image
00256 void Image::copy( Image* dst, Image* src, const OfxPointI& dstCorner,
00257                   const OfxPointI& srcCorner, const OfxPointI& count )
00258 {
00259         using namespace boost::gil;
00260         switch( src->getComponentsType() )
00261         {
00262                 case ofx::imageEffect::ePixelComponentRGBA:
00263                         switch( src->getBitDepth() )
00264                         {
00265                                 case ofx::imageEffect::eBitDepthUByte:
00266                                 {
00267                                         rgba8_view_t sView = src->getGilView<rgba8_view_t >();
00268                                         Image::copy( dst, sView, dstCorner, srcCorner, count );
00269                                         break;
00270                                 }
00271                                 case ofx::imageEffect::eBitDepthUShort:
00272                                 {
00273                                         rgba16_view_t sView = src->getGilView<rgba16_view_t >();
00274                                         Image::copy( dst, sView, dstCorner, srcCorner, count );
00275                                         break;
00276                                 }
00277                                 case ofx::imageEffect::eBitDepthFloat:
00278                                 {
00279                                         rgba32f_view_t sView = src->getGilView<rgba32f_view_t >();
00280                                         Image::copy( dst, sView, dstCorner, srcCorner, count );
00281                                         break;
00282                                 }
00283                                 default:
00284                                         break;
00285                         }
00286                         break;
00287                 case ofx::imageEffect::ePixelComponentAlpha:
00288                         switch( src->getBitDepth() )
00289                         {
00290                                 case ofx::imageEffect::eBitDepthUByte:
00291                                 {
00292                                         gray8_view_t sView = src->getGilView<gray8_view_t >();
00293                                         Image::copy( dst, sView, dstCorner, srcCorner, count );
00294                                         break;
00295                                 }
00296                                 case ofx::imageEffect::eBitDepthUShort:
00297                                 {
00298                                         gray16_view_t sView = src->getGilView<gray16_view_t >();
00299                                         Image::copy( dst, sView, dstCorner, srcCorner, count );
00300                                         break;
00301                                 }
00302                                 case ofx::imageEffect::eBitDepthFloat:
00303                                 {
00304                                         gray32f_view_t sView = src->getGilView<gray32f_view_t >();
00305                                         Image::copy( dst, sView, dstCorner, srcCorner, count );
00306                                         break;
00307                                 }
00308                                 default:
00309                                         break;
00310                         }
00311                         break;
00312                 default:
00313                         break;
00314         }
00315 }
00316 
00317 }
00318 }
00319 }