TuttleOFX  1
TuttleOFX/libraries/tuttle/src/tuttle/host/attribute/Image.cpp
Go to the documentation of this file.
00001 #include "Image.hpp"
00002 
00003 #if(TUTTLE_PNG_EXPORT_BETWEEN_NODES)
00004 #define int_p_NULL (int *)NULL
00005  // Should be included first to avoid setjmp.h include troubles
00006  #include <boost/gil/extension/io/png_io.hpp>
00007 #endif
00008 
00009 #include <tuttle/host/attribute/ClipImage.hpp>
00010 #include <tuttle/host/Core.hpp>
00011 #include <tuttle/common/utils/global.hpp>
00012 
00013 #include <boost/gil/image.hpp>
00014 #include <boost/gil/image_view.hpp>
00015 #include <boost/gil/typedefs.hpp>
00016 
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 #if(TUTTLE_PNG_EXPORT_BETWEEN_NODES)
00128 void Image::debugSaveAsPng( const std::string& filename )
00129 {
00130         using namespace boost::gil;
00131         switch( getComponentsType() )
00132         {
00133                 case ofx::imageEffect::ePixelComponentRGB:
00134                         switch( getBitDepth() )
00135                         {
00136                                 case ofx::imageEffect::eBitDepthUByte:
00137                                 {
00138                                         rgb8_view_t view = getGilView<rgb8_view_t>();
00139                                         png_write_view( filename, view );
00140                                         break;
00141                                 }
00142                                 case ofx::imageEffect::eBitDepthUShort:
00143                                 {
00144                                         rgb16_view_t view = getGilView<rgb16_view_t>();
00145                                         png_write_view( filename, view );
00146                                         break;
00147                                 }
00148                                 case ofx::imageEffect::eBitDepthFloat:
00149                                 {
00150                                         rgb32f_view_t view = getGilView<rgb32f_view_t>();
00151                                         png_write_view( filename, color_converted_view<rgb8_pixel_t>( view ) );
00152                                         break;
00153                                 }
00154                                 default:
00155                                         break;
00156                         }
00157                         break;
00158                 case ofx::imageEffect::ePixelComponentRGBA:
00159                         switch( getBitDepth() )
00160                         {
00161                                 case ofx::imageEffect::eBitDepthUByte:
00162                                 {
00163                                         rgba8_view_t view = getGilView<rgba8_view_t>();
00164                                         png_write_view( filename, view );
00165                                         break;
00166                                 }
00167                                 case ofx::imageEffect::eBitDepthUShort:
00168                                 {
00169                                         rgba16_view_t view = getGilView<rgba16_view_t>();
00170                                         png_write_view( filename, view );
00171                                         break;
00172                                 }
00173                                 case ofx::imageEffect::eBitDepthFloat:
00174                                 {
00175                                         rgba32f_view_t view = getGilView<rgba32f_view_t>();
00176                                         png_write_view( filename, color_converted_view<rgba8_pixel_t>( view ) );
00177                                         break;
00178                                 }
00179                                 default:
00180                                         break;
00181                         }
00182                         break;
00183                 case ofx::imageEffect::ePixelComponentAlpha:
00184                         switch( getBitDepth() )
00185                         {
00186                                 case ofx::imageEffect::eBitDepthUByte:
00187                                 {
00188                                         gray8_view_t view = getGilView<gray8_view_t>();
00189                                         png_write_view( filename, view );
00190                                         break;
00191                                 }
00192                                 case ofx::imageEffect::eBitDepthUShort:
00193                                 {
00194                                         gray16_view_t view = getGilView<gray16_view_t>();
00195                                         png_write_view( filename, view );
00196                                         break;
00197                                 }
00198                                 case ofx::imageEffect::eBitDepthFloat:
00199                                 {
00200                                         gray32f_view_t view = getGilView<gray32f_view_t>();
00201                                         png_write_view( filename, color_converted_view<rgb8_pixel_t>( view ) );
00202                                         break;
00203                                 }
00204                                 default:
00205                                         break;
00206                         }
00207                         break;
00208                 default:
00209                         TUTTLE_TLOG( TUTTLE_WARNING, "Cannot write png debug image for file '" + filename + "': unsupported component type." );
00210                         break;
00211         }
00212 }
00213 #endif
00214 
00215 /// Copy from gil image view to Image
00216 template < class S_VIEW >
00217 void Image::copy( Image* dst, S_VIEW& src, const OfxPointI& dstCorner,
00218                   const OfxPointI& srcCorner, const OfxPointI& count )
00219 {
00220         using namespace boost::gil;
00221         // Create destination
00222         switch( dst->getComponentsType() )
00223         {
00224                 case ofx::imageEffect::ePixelComponentRGBA:
00225                         switch( dst->getBitDepth() )
00226                         {
00227                                 case ofx::imageEffect::eBitDepthUByte:
00228                                 {
00229                                         rgba8_view_t dView = dst->getGilView<rgba8_view_t >();
00230                                         Image::copy( dView, src, dstCorner, srcCorner, count );
00231                                         break;
00232                                 }
00233                                 case ofx::imageEffect::eBitDepthUShort:
00234                                 {
00235                                         rgba16_view_t dView = dst->getGilView<rgba16_view_t >();
00236                                         Image::copy( dView, src, dstCorner, srcCorner, count );
00237                                         break;
00238                                 }
00239                                 case ofx::imageEffect::eBitDepthFloat:
00240                                 {
00241                                         rgba32f_view_t dView = dst->getGilView<rgba32f_view_t >();
00242                                         Image::copy( dView, src, dstCorner, srcCorner, count );
00243                                         break;
00244                                 }
00245                                 default:
00246                                         break;
00247                         }
00248                         break;
00249                 case ofx::imageEffect::ePixelComponentAlpha:
00250                         switch( dst->getBitDepth() )
00251                         {
00252                                 case ofx::imageEffect::eBitDepthUByte:
00253                                 {
00254                                         gray8_view_t dView = dst->getGilView<gray8_view_t >();
00255                                         Image::copy( dView, src, dstCorner, srcCorner, count );
00256                                         break;
00257                                 }
00258                                 case ofx::imageEffect::eBitDepthUShort:
00259                                 {
00260                                         gray16_view_t dView = dst->getGilView<gray16_view_t >();
00261                                         Image::copy( dView, src, dstCorner, srcCorner, count );
00262                                         break;
00263                                 }
00264                                 case ofx::imageEffect::eBitDepthFloat:
00265                                 {
00266                                         gray32f_view_t dView = dst->getGilView<gray32f_view_t >();
00267                                         Image::copy( dView, src, dstCorner, srcCorner, count );
00268                                         break;
00269                                 }
00270                                 default:
00271                                         break;
00272                         }
00273                         break;
00274                 default:
00275                         break;
00276         }
00277 }
00278 
00279 /// Copy from Image to Image
00280 void Image::copy( Image* dst, Image* src, const OfxPointI& dstCorner,
00281                   const OfxPointI& srcCorner, const OfxPointI& count )
00282 {
00283         using namespace boost::gil;
00284         switch( src->getComponentsType() )
00285         {
00286                 case ofx::imageEffect::ePixelComponentRGBA:
00287                         switch( src->getBitDepth() )
00288                         {
00289                                 case ofx::imageEffect::eBitDepthUByte:
00290                                 {
00291                                         rgba8_view_t sView = src->getGilView<rgba8_view_t >();
00292                                         Image::copy( dst, sView, dstCorner, srcCorner, count );
00293                                         break;
00294                                 }
00295                                 case ofx::imageEffect::eBitDepthUShort:
00296                                 {
00297                                         rgba16_view_t sView = src->getGilView<rgba16_view_t >();
00298                                         Image::copy( dst, sView, dstCorner, srcCorner, count );
00299                                         break;
00300                                 }
00301                                 case ofx::imageEffect::eBitDepthFloat:
00302                                 {
00303                                         rgba32f_view_t sView = src->getGilView<rgba32f_view_t >();
00304                                         Image::copy( dst, sView, dstCorner, srcCorner, count );
00305                                         break;
00306                                 }
00307                                 default:
00308                                         break;
00309                         }
00310                         break;
00311                 case ofx::imageEffect::ePixelComponentAlpha:
00312                         switch( src->getBitDepth() )
00313                         {
00314                                 case ofx::imageEffect::eBitDepthUByte:
00315                                 {
00316                                         gray8_view_t sView = src->getGilView<gray8_view_t >();
00317                                         Image::copy( dst, sView, dstCorner, srcCorner, count );
00318                                         break;
00319                                 }
00320                                 case ofx::imageEffect::eBitDepthUShort:
00321                                 {
00322                                         gray16_view_t sView = src->getGilView<gray16_view_t >();
00323                                         Image::copy( dst, sView, dstCorner, srcCorner, count );
00324                                         break;
00325                                 }
00326                                 case ofx::imageEffect::eBitDepthFloat:
00327                                 {
00328                                         gray32f_view_t sView = src->getGilView<gray32f_view_t >();
00329                                         Image::copy( dst, sView, dstCorner, srcCorner, count );
00330                                         break;
00331                                 }
00332                                 default:
00333                                         break;
00334                         }
00335                         break;
00336                 default:
00337                         break;
00338         }
00339 }
00340 
00341 }
00342 }
00343 }