TuttleOFX
1
|
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 }