void image_node_renderer_t::render( const Imath::Box2i& roi) { RAMEN_ASSERT( has_context_); RAMEN_ASSERT( !roi.isEmpty()); n_->set_interest( roi); breadth_first_inputs_apply( *n_, boost::bind( &image_node_t::calc_inputs_interest_fun, _1, new_context_)); depth_first_inputs_search( *n_, boost::bind( &image_node_t::calc_defined_fun, _1, new_context_)); depth_first_inputs_search( *n_, boost::bind( &image_node_t::subsample_areas_fun, _1, new_context_)); if( do_log) depth_first_inputs_search( *n_, test_empty_images()); depth_first_inputs_search( *n_, boost::bind( &node_t::clear_hash, _1)); depth_first_inputs_search( *n_, boost::bind( &node_t::calc_hash_str, _1, new_context_)); if( do_log) depth_first_inputs_search( *n_, print_areas()); try { n_->recursive_process( new_context_); render_done_ = true; } catch( std::bad_alloc&) { throw boost::enable_error_info( std::bad_alloc()); } }
AcesOutputFile::AcesOutputFile (const std::string &name, const Imath::Box2i &displayWindow, const Imath::Box2i &dataWindow, RgbaChannels rgbaChannels, float pixelAspectRatio, const Imath::V2f screenWindowCenter, float screenWindowWidth, LineOrder lineOrder, Compression compression, int numThreads) : _data (new Data) { checkCompression (compression); Header newHeader (displayWindow, dataWindow.isEmpty()? displayWindow: dataWindow, pixelAspectRatio, screenWindowCenter, screenWindowWidth, lineOrder, compression); addChromaticities (newHeader, acesChromaticities()); addAdoptedNeutral (newHeader, acesChromaticities().white); _data->rgbaFile = new RgbaOutputFile (name.c_str(), newHeader, rgbaChannels, numThreads); _data->rgbaFile->setYCRounding (7, 6); }
void exposure_node_t::do_process( const image::const_image_view_t& src, const image::image_view_t& dst, const render::render_context_t& context) { image::const_image_view_t src_view; image::image_view_t dst_view; Imath::Box2i area; if( input(1)) { boost::gil::copy_pixels( src, dst); area = intersect( input(1)->defined(), defined()); if( area.isEmpty()) return; src_view = input(0)->const_subimage_view( area); dst_view = subimage_view( area); } else { src_view = src; dst_view = dst; } boost::gil::tbb_transform_pixels( src_view, dst_view, exposure_fun( get_value<float>( param( "exp")))); if( input(1)) image::key_mix( src_view, dst_view, boost::gil::nth_channel_view( input(1)->const_subimage_view( area), 3), dst_view); }
TiledRgbaOutputFile::TiledRgbaOutputFile (const char name[], int tileXSize, int tileYSize, LevelMode mode, LevelRoundingMode rmode, const Imath::Box2i &displayWindow, const Imath::Box2i &dataWindow, RgbaChannels rgbaChannels, float pixelAspectRatio, const Imath::V2f screenWindowCenter, float screenWindowWidth, LineOrder lineOrder, Compression compression, int numThreads) : _outputFile (0), _toYa (0) { Header hd (displayWindow, dataWindow.isEmpty()? displayWindow: dataWindow, pixelAspectRatio, screenWindowCenter, screenWindowWidth, lineOrder, compression); insertChannels (hd, rgbaChannels, name); hd.setTileDescription (TileDescription (tileXSize, tileYSize, mode, rmode)); _outputFile = new TiledOutputFile (name, hd, numThreads); if (rgbaChannels & WRITE_Y) _toYa = new ToYa (*_outputFile, rgbaChannels); }
RgbaOutputFile::RgbaOutputFile (const char name[], const Imath::Box2i &displayWindow, const Imath::Box2i &dataWindow, RgbaChannels rgbaChannels, float pixelAspectRatio, const Imath::V2f screenWindowCenter, float screenWindowWidth, LineOrder lineOrder, Compression compression): _outputFile (0) { Header hd (displayWindow, dataWindow.isEmpty()? displayWindow: dataWindow, pixelAspectRatio, screenWindowCenter, screenWindowWidth, lineOrder, compression); ChannelList ch; if (rgbaChannels & WRITE_R) ch.insert ("R", Channel (HALF, 1, 1)); if (rgbaChannels & WRITE_G) ch.insert ("G", Channel (HALF, 1, 1)); if (rgbaChannels & WRITE_B) ch.insert ("B", Channel (HALF, 1, 1)); if (rgbaChannels & WRITE_A) ch.insert ("A", Channel (HALF, 1, 1)); hd.channels() = ch; _outputFile = new OutputFile (name, hd); }
void flipbook_t::set_format( const Imath::Box2i& f, float aspect, int subsample) { RAMEN_ASSERT( !f.isEmpty()); format_ = ImathExt::scale( f, 1.0f / subsample); buffer_ = image::buffer_t( format_, 4); aspect_ = aspect; }
void expand_node_t::do_process( const render::context_t& context) { Imath::Box2i area = ImathExt::intersect( input_as<image_node_t>()->defined(), defined()); if( area.isEmpty()) return; boost::gil::copy_pixels( input_as<image_node_t>()->const_subimage_view( area), subimage_view( area)); }
void crop_node_t::do_process( const render::render_context_t& context) { Imath::Box2i area = intersect( input()->defined(), defined()); if( area.isEmpty()) return; boost::gil::copy_pixels( input()->const_subimage_view( area), subimage_view( area)); }
void copy_channels_node_t::do_calc_bounds( const render::render_context_t& context) { Imath::Box2i rod1 = input(0)->bounds(); Imath::Box2i rod2 = input(1)->bounds(); int ch_r = get_value<int>( param( "red")); int ch_g = get_value<int>( param( "green")); int ch_b = get_value<int>( param( "blue")); int ch_a = get_value<int>( param( "alpha")); // use alpha from input 1 if( ch_a == copy_source) { set_bounds( rod1); return; } // alpha comes from input2 if( ch_a != set_one && ch_a != set_zero) { set_bounds( rod2); return; } // alpha is zero or one, look at the other channels Imath::Box2i rod; if( ch_r == copy_source) rod = rod1; else { if( ch_r != set_zero && ch_r != set_one) rod = rod2; } if( ch_g == copy_source) rod.extendBy( rod1); else { if( ch_g != set_zero && ch_r != set_one) rod.extendBy( rod2); } if( ch_b == copy_source) rod.extendBy( rod1); else { if( ch_b != set_zero && ch_r != set_one) rod.extendBy( rod2); } if( rod.isEmpty()) rod = rod1; set_bounds( rod); }
void copy_channels_node_t::do_calc_defined( const render::render_context_t& context) { Imath::Box2i def1 = input(0)->defined(); Imath::Box2i def2 = input(1)->defined(); int ch_r = get_value<int>( param( "red")); int ch_g = get_value<int>( param( "green")); int ch_b = get_value<int>( param( "blue")); int ch_a = get_value<int>( param( "alpha")); // use alpha from input 1 if( ch_a == copy_source) { set_defined( def1); return; } // alpha comes from input2 if( ch_a != set_one && ch_a != set_zero) { set_defined( def2); return; } // alpha is zero or one, look at the other channels Imath::Box2i def; if( ch_r == copy_source) def = def1; else { if( ch_r != set_zero && ch_r != set_one) def = def2; } if( ch_g == copy_source) def.extendBy( def1); else { if( ch_g != set_zero && ch_r != set_one) def.extendBy( def2); } if( ch_b == copy_source) def.extendBy( def1); else { if( ch_b != set_zero && ch_r != set_one) def.extendBy( def2); } if( def.isEmpty()) def = def1; set_defined( def); }
image_t *clip_t::get_output_image( OfxTime time, OfxRectD *optionalBounds) { RAMEN_ASSERT( node()); RAMEN_ASSERT( node()->composition()); RAMEN_ASSERT( !node()->image_empty()); RAMEN_ASSERT( time == node()->composition()->frame()); RAMEN_ASSERT( getComponents() == kOfxImageComponentRGBA); RAMEN_ASSERT( getPixelDepth() == kOfxBitDepthFloat); Imath::Box2i area; if( optionalBounds) { area = Imath::Box2i( Imath::V2i( optionalBounds->x1, optionalBounds->y1), Imath::V2i( optionalBounds->x2 - 1, optionalBounds->y2 - 1)); area = Imath::scale( area, 1.0f / node()->render_context().subsample); area = node()->vertical_flip( area); } else area = node()->defined(); if( area.isEmpty()) { #ifndef NDEBUG DLOG( INFO) << "clip_t::getOutputImage, node = " << node()->name() << ", area == empty"; #endif return 0; } image::const_image_view_t view( node()->const_subimage_view( area)); int rowbytes; void *ptr = view_get_ptr_and_stride( view, rowbytes); // convert to OFX coordinate sys area = node()->vertical_flip( area); OfxRectI bounds; bounds.x1 = area.min.x; bounds.y1 = area.min.y; bounds.x2 = area.max.x + 1; bounds.y2 = area.max.y + 1; #ifndef NDEBUG DLOG( INFO) << "clip_t::getOutputImage, node = " << node()->name(); #endif return new image_t( *this, node()->image(), 1.0 / node()->render_context().subsample, ptr, bounds, bounds, rowbytes, std::string( "")); }
void set_matte_node_t::do_process( const render::context_t& context) { if( defined().isEmpty()) return; boost::gil::tbb_transform_pixels( input_as<image_node_t>( 0)->const_subimage_view( defined()), image_view(), copy_rgb_and_clear_alpha()); Imath::Box2i area = ImathExt::intersect( defined(), input_as<image_node_t>( 1)->defined()); if( !area.isEmpty()) boost::gil::tbb_copy_pixels( boost::gil::nth_channel_view( input_as<image_node_t>( 1)->const_subimage_view( area), 3), boost::gil::nth_channel_view( subimage_view( area), 3)); if( get_value<bool>( param( "premultiply"))) image::premultiply( image_view(), image_view()); }
void keyer_node_t::sample_input( const Imath::Box2i& area, std::vector<Imath::Color3f>& colors) const { if( input_pixels_.empty()) return; Imath::Box2i subarea = Imath::intersect( area, input_data_window_); if( subarea.isEmpty()) return; Imath::V2i p; for( p.y = subarea.min.y; p.y <= subarea.max.y; ++p.y) { for( p.x = subarea.min.x; p.x <= subarea.max.x; ++p.x) { image::pixel_t px( input_pixels_.const_rgba_view()( p.x - input_data_window_.min.x, p.y - input_data_window_.min.y)); colors.push_back( Imath::Color3f( boost::gil::get_color( px, boost::gil::red_t()), boost::gil::get_color( px, boost::gil::green_t()), boost::gil::get_color( px, boost::gil::blue_t()))); } } }
image_t *clip_t::get_input_image( OfxTime time, OfxRectD *optionalBounds) { RAMEN_ASSERT( node()); RAMEN_ASSERT( node()->composition()); RAMEN_ASSERT( port_ != -1); RAMEN_ASSERT( getPixelDepth() == kOfxBitDepthFloat); image_node_t *in = node()->input_as<image_node_t>( port()); if( !in) { #ifndef NDEBUG DLOG( INFO) << "clip_t::getImage, node = " << node()->name() << ", port = " << port() << ", result = 0"; #endif return 0; } render::context_t context = node()->render_context(); context.composition = node()->composition(); context.result_node = in; context.frame = time; render::context_guard_t guard( node()->composition()->current_context(), in); render::image_node_renderer_t r( context); Imath::Box2i area; if( optionalBounds) { // TODO: is this correct if the effect does not support tiles? area = Imath::Box2i( Imath::V2i( optionalBounds->x1, optionalBounds->y1), Imath::V2i( optionalBounds->x2 - 1, optionalBounds->y2 - 1)); area = node()->vertical_flip( area); r.render( area); area.min.x = optionalBounds->x1; area.min.y = optionalBounds->y1; area.max.x = optionalBounds->x2 - 1; area.max.y = optionalBounds->y2 - 1; area = node()->vertical_flip( area); area = intersect( in->defined(), area); } else { r.render(); area = in->defined(); } if( area.isEmpty()) { #ifndef NDEBUG DLOG( INFO) << "clip_t::getImage, node = " << node()->name() << ", port = " << port() << ", area == empty"; #endif return 0; } image::buffer_t pixels = in->image(); image::const_image_view_t view( in->const_subimage_view( area)); area = node()->vertical_flip( area); OfxRectI bounds; bounds.x1 = area.min.x; bounds.y1 = area.min.y; bounds.x2 = area.max.x + 1; bounds.y2 = area.max.y + 1; std::stringstream s; for( int i = 0; i < 16; ++i) s << (int) in->digest()[i]; #ifndef NDEBUG if( optionalBounds) DLOG( INFO) << "clip_t::getImage, node = " << node()->name() << ", port = " << port() << ", bounds = " << *optionalBounds; else DLOG( INFO) << "clip_t::getImage, node = " << node()->name() << ", port = " << port(); #endif image_t *result = 0; if( getComponents() == kOfxImageComponentRGBA) { int rowbytes; void *ptr = view_get_ptr_and_stride( view, rowbytes); result = new image_t( *this, pixels, 1.0 / node()->render_context().subsample, ptr, bounds, bounds, rowbytes, s.str()); } else { // TODO: create an gray scale image and copy the alpha channel RAMEN_ASSERT( 0); } in->release_image(); return result; }
OfxRectD clip_t::getRegionOfDefinition( OfxTime time) const { RAMEN_ASSERT( node()); const image_node_t *in = 0; bool use_default = false; bool restore_time = false; float saved_frame; // calling getRoD for the output clip does not make a lot of sense, but some plugins do... if( port_ == -1) in = node(); else // normal case in = node()->input_as<const image_node_t>( port_); if( !in) { in = node(); use_default = true; } if( node()->composition()) { saved_frame = node()->composition()->frame(); if( saved_frame != time) { restore_time = true; composition_t *c = const_cast<composition_t*>( node()->composition()); c->set_frame( time); } } Imath::Box2i b; if( use_default) { for( int i = 0; i < in->num_inputs(); ++i) { if( const image_node_t *src = in->input_as<const image_node_t>( i)) b.extendBy( src->bounds()); } if( b.isEmpty()) { if( in->composition()) b = node()->composition()->default_format().area(); else b = preferences_t::Instance().default_format().area(); } } else b = in->bounds(); b = node()->vertical_flip( b); OfxRectD v; v.x1 = b.min.x; v.y1 = b.min.y; v.x2 = b.max.x + 1; v.y2 = b.max.y + 1; if( restore_time) { composition_t *c = const_cast<composition_t*>( node()->composition()); c->set_frame( saved_frame); } #ifndef NDEBUG DLOG( INFO) << "clip_t::getRoD, node = " << node()->name() << ", port = " << port() << ", result = " << v; #endif return v; }
OFX::Host::ImageEffect::Image* clip_t::get_input_image( OfxTime time, OfxRectD *optionalBounds) { assert( node()); assert( node()->composition()); node_t *in = node()->input( port()); if( !in) return 0; render::render_context_t context = node()->render_context(); context.composition = node()->composition(); context.result_node = in; context.time = time; Imath::Box2i area; if( optionalBounds) { // TODO: is this correct if the effect does not support tiles? area = Imath::Box2i( Imath::V2i( optionalBounds->x1, optionalBounds->y1), Imath::V2i( optionalBounds->x2 - 1, optionalBounds->y2 - 1)); area = node()->vertical_flip_box( area); } else area = scale( node()->defined(), context.subsample); render::renderer_t r( context, true, false); r.render( area); if( optionalBounds) { area.min.x = optionalBounds->x1; area.min.y = optionalBounds->y1; area.max.x = optionalBounds->x2 - 1; area.max.y = optionalBounds->y2 - 1; area = node()->vertical_flip_box( area); area = intersect( in->defined(), area); } else area = in->defined(); if( area.isEmpty()) return 0; image::image_buffer_t pixels = in->image(); image::const_image_view_t view( in->const_subimage_view( area)); int rowbytes; void *ptr = view_get_ptr_and_stride( view, rowbytes); area = node()->vertical_flip_box( area); OfxRectI bounds; bounds.x1 = area.min.x; bounds.y1 = area.min.y; bounds.x2 = area.max.x + 1; bounds.y2 = area.max.y + 1; std::stringstream s; for( int i = 0; i < 16; ++i) s << (int) in->digest()[i]; input_image_t *result = new input_image_t( *this, pixels, 1.0 / node()->render_context().subsample, ptr, bounds, bounds, rowbytes, s.str()); in->release_image(); return result; }