TuttleOFX  1
TuttleOFX/libraries/tuttle/src/tuttle/plugin/ofxToGil/image.hpp
Go to the documentation of this file.
00001 #ifndef _TUTTLE_OFXTOGIL_IMAGE_HPP_
00002 #define _TUTTLE_OFXTOGIL_IMAGE_HPP_
00003 
00004 #include <tuttle/plugin/image.hpp>
00005 
00006 #include <ofxsImageEffect.h>
00007 
00008 #include <boost/gil/utilities.hpp>
00009 #include <boost/gil/image.hpp>
00010 #include <boost/gil/image_view.hpp>
00011 #include <boost/gil/image_view_factory.hpp>
00012 
00013 
00014 namespace tuttle {
00015 namespace plugin {
00016 
00017 /**
00018  * @brief Return a full gil view of an image.
00019  *        If we only have a tiled image, we use subimage_view to fit to the rod.
00020  * @param img the ofx image object
00021  * @param rod normally we don't need this parameter because we can get it from the image,
00022  *            but there is a bug in nuke (which return the bounds),
00023  *            so we need to use the rod of the clip and not from the image.
00024  */
00025 template<class View>
00026 View getGilView( OFX::Image* img, const OfxRectI& pixelRod, const EImageOrientation orientation )
00027 {
00028         using namespace boost::gil;
00029         typedef typename View::value_type Pixel;
00030         //TUTTLE_TLOG( TUTTLE_TRACE, "getGilView => " << img->getUniqueIdentifier() );
00031 
00032         //      OfxRectI imgrod = img->getRegionOfDefinition(); // bug in nuke returns bounds... not the clip rod with renderscale...
00033         const OfxRectI bounds = img->getBounds();
00034 //      TUTTLE_TLOG_VAR( TUTTLE_TRACE, bounds );
00035 //      TUTTLE_TLOG_VAR( TUTTLE_TRACE, imgrod );
00036 //      TUTTLE_TLOG_VAR( TUTTLE_TRACE, rod );
00037         const point2<int> tileSize = point2<int>( bounds.x2 - bounds.x1,
00038                                             bounds.y2 - bounds.y1 );
00039 
00040         // Build view
00041         /**
00042          * About image ordering from OpenFX documentation:
00043          * 
00044          * Images are always left to right, bottom to top,
00045          * with the pixel data pointer being at the bottom left of the image.
00046          * The pixels in a scan line are contiguously packed.
00047          * Scanlines need not be contiguously packed.
00048          * The number of bytes between between a pixel in the same column,
00049          * but separated by a scan line is known as the rowbytes of an image.
00050          * Rowbytes can be negative, allowing for compositing systems with a native
00051          * top to bottom scanline order to trivially support bottom to top images.
00052          */
00053         View tileView = interleaved_view( tileSize.x, tileSize.y,
00054                                                                                 static_cast<Pixel*>( img->getPixelData() ),
00055                                                                                 img->getRowDistanceBytes() );
00056         
00057         TUTTLE_TLOG( TUTTLE_INFO, "[OFX to Gil] Row distance from image " << img->getRowDistanceBytes() << " bytes" );
00058         TUTTLE_TLOG( TUTTLE_INFO, "[OFX to Gil] Tile view, row size = " << tileView.pixels().row_size() );
00059         
00060         View fullView;
00061         const bool isTile = (
00062                 bounds.x1 != pixelRod.x1 || bounds.y1 != pixelRod.y1 ||
00063             bounds.x2 != pixelRod.x2 || bounds.y2 != pixelRod.y2 );
00064         // if the tile is equals to the full image
00065         // directly return the tile
00066         if( ! isTile )
00067         {
00068                 TUTTLE_TLOG( TUTTLE_INFO, "[OFX to Gil] Tile is equal to the full view" );
00069                 fullView = tileView;
00070         }
00071         else
00072         {
00073                 // view the tile as a full image
00074                 ////TUTTLE_TLOG( TUTTLE_TRACE, "Tile to full view" );
00075                 fullView = subimage_view( tileView, pixelRod.x1 - bounds.x1, pixelRod.y1 - bounds.y1, pixelRod.x2 - pixelRod.x1, pixelRod.y2 - pixelRod.y1 );
00076         }
00077         
00078         TUTTLE_TLOG( TUTTLE_INFO, "[OFX to Gil] Full view, row size = " << fullView.pixels().row_size() );
00079         
00080         View resView = fullView;
00081         switch( orientation )
00082         {
00083                 case eImageOrientationIndependant: // use memory order
00084                 {
00085                         TUTTLE_TLOG( TUTTLE_INFO, "[OFX to Gil] Image orientation independant"  );
00086                         if( isTile ) // can't manage ordering
00087                                 break;
00088 
00089                         if( img->getRowDistanceBytes() < 0 ) // if the host use buffer ordered from top to bottom
00090                         {
00091                                 resView = flipped_up_down_view( fullView );
00092                         }
00093                         break;
00094                 }
00095                 case eImageOrientationFromTopToBottom:
00096                 {
00097                         TUTTLE_TLOG( TUTTLE_INFO, "[OFX to Gil] Image orientation from top to bottom"  );
00098                         BOOST_ASSERT( ! isTile ); // can't manage ordering with tiles currently (no RoW information in OpenFX)
00099 
00100                         resView = flipped_up_down_view( fullView );
00101                         break;
00102                 }
00103                 case eImageOrientationFromBottomToTop:
00104                 {
00105                         TUTTLE_TLOG( TUTTLE_INFO, "[OFX to Gil] Image orientation from bottom to top"  );
00106                         // by default in OpenFX we are in this order
00107                         break;
00108                 }
00109         }
00110         
00111         ////TUTTLE_TLOG_VAR( TUTTLE_TRACE, resView.pixels().row_size() );
00112         return resView;
00113 }
00114 
00115 
00116 }
00117 }
00118 
00119 
00120 
00121 #endif
00122