void blur_channels_node_t::blur_channel( int ch, const Imath::Box2i& area, const boost::gil::gray32f_view_t& tmp, const Imath::V2f& radius, int iters, blur_border_mode border) { if( border != border_black) { int hradius = std::ceil( radius.x); int vradius = std::ceil( radius.y); int border_x0 = std::min( area.min.x - defined().min.x, hradius); int border_y0 = std::min( area.min.y - defined().min.y, vradius); int border_x1 = std::min( defined().max.x - area.max.x, hradius); int border_y1 = std::min( defined().max.y - area.max.y, vradius); Imath::Box2i box( area); box.min.x -= border_x0; box.min.y -= border_y0; box.max.x += border_x1; box.max.y += border_y1; if( border == border_repeat) boost::gil::repeat_border_pixels( boost::gil::nth_channel_view( subimage_view( box), ch), border_x0, border_y0, border_x1, border_y1); else boost::gil::reflect_border_pixels( boost::gil::nth_channel_view( subimage_view( box), ch), border_x0, border_y0, border_x1, border_y1); } image::box_blur_channel( boost::gil::nth_channel_view( const_image_view(), ch), tmp, boost::gil::nth_channel_view( image_view(), ch), radius.x, radius.y, iters); }
void keyer3d_node_t::do_process( const render::context_t& context) { image_node_t *in0 = input_as<image_node_t>( 0); float gtol = get_value<float>( param( "gtol")); float gsoft = get_value<float>( param( "gsoft")); keyer().set_tol_soft_factors( gtol, gsoft); if( !input(1)) { Imath::Box2i area( Imath::intersect( defined(), in0->defined())); if( area.isEmpty()) return; boost::gil::tbb_transform_pixels( in0->const_subimage_view( area), subimage_view( area), key3d_fun( keyer())); } else { image_node_t *in1 = input_as<image_node_t>( 1); Imath::Box2i area( Imath::intersect( Imath::intersect( defined(), in0->defined()), in1->defined())); if( area.isEmpty()) return; boost::gil::tbb_transform2_pixels( in0->const_subimage_view( area), in1->const_subimage_view( area), subimage_view( area), key3d_fun( keyer())); } }
void blur_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)); int bmode = get_value<int>( param( "border")); if( bmode != border_black) { int border_x0 = area.min.x - defined().min.x; int border_y0 = area.min.y - defined().min.y; int border_x1 = defined().max.x - area.max.x; int border_y1 = defined().max.y - area.max.y; if( bmode == border_repeat) boost::gil::repeat_border_pixels( image_view(), border_x0, border_y0, border_x1, border_y1); else boost::gil::reflect_border_pixels( image_view(), border_x0, border_y0, border_x1, border_y1); } int channels = get_value<int>( param( "channels")); Imath::V2f radius = get_value<Imath::V2f>( param( "radius")); int iters = get_value<int>( param( "iters")); radius.x /= context.subsample; radius.y /= context.subsample; switch( channels) { case channels_rgba: image::box_blur_rgba( const_image_view(), image_view(), radius.x, radius.y, iters); break; case channels_rgb: { image::box_blur_rgba( const_image_view(), image_view(), radius.x, radius.y, iters); boost::gil::fill_pixels( boost::gil::nth_channel_view( image_view(), 3), boost::gil::gray32f_pixel_t( 0)); boost::gil::copy_pixels( boost::gil::nth_channel_view( input()->const_subimage_view( area), 3), boost::gil::nth_channel_view( subimage_view( area), 3)); } break; case channels_alpha: { image::box_blur_channel( boost::gil::nth_channel_view( const_image_view(), 3), boost::gil::nth_channel_view( image_view(), 3), radius.x, radius.y, iters); } break; } }
void copy_channels_node_t::do_process( const render::context_t& context) { Imath::Box2i src1_area( ImathExt::intersect( input_as<image_node_t>(0)->defined(), defined())); image::const_image_view_t src1( input_as<image_node_t>(0)->const_subimage_view( src1_area)); Imath::Box2i src2_area( ImathExt::intersect( input_as<image_node_t>(1)->defined(), defined())); image::const_image_view_t src2( input_as<image_node_t>(1)->const_subimage_view( src2_area)); image::image_view_t dst1( subimage_view( src1_area)); image::image_view_t dst2( subimage_view( src2_area)); int ch = get_value<int>( param( "red")); if( ch == copy_source) copy_channel( src1, 0, dst1, 0); else copy_channel( src2, ch-1, dst2, 0); ch = get_value<int>( param( "green")); if( ch == copy_source) copy_channel( src1, 1, dst1, 1); else copy_channel( src2, ch-1, dst2, 1); ch = get_value<int>( param( "blue")); if( ch == copy_source) copy_channel( src1, 2, dst1, 2); else copy_channel( src2, ch-1, dst2, 2); ch = get_value<int>( param( "alpha")); switch( ch) { case copy_source: copy_channel( src1, 3, dst1, 3); break; case set_one: case set_zero: { Imath::Box2i area( ImathExt::intersect( defined(), format())); copy_channel( src1, ch-1, subimage_view( area), 3); } break; default: copy_channel( src2, ch-1, dst2, 3); } }
Symbol match(PcaContext& ctx, const TSomeView& imgv) const { boost::gil::gil_function_requires<boost::gil::ImageViewConcept<TSomeView> >(); boost::gil::gil_function_requires<boost::gil::ColorSpacesCompatibleConcept< typename boost::gil::color_space_type<TSomeView>::type, typename boost::gil::color_space_type<ConstViewT>::type> >(); boost::gil::gil_function_requires<boost::gil::ChannelsCompatibleConcept< typename boost::gil::channel_type<TSomeView>::type, typename boost::gil::channel_type<ConstViewT>::type> >(); assert(static_cast<size_t>(imgv.width()) <= cellWidth()); assert(static_cast<size_t>(imgv.height()) <= cellHeight()); typedef boost::gil::layout< typename boost::gil::color_space_type<ConstViewT>::type, typename boost::gil::channel_mapping_type<TSomeView>::type > LayoutT; typedef typename float_channel_type<typename boost::gil::channel_type<ConstViewT>::type>::type FloatChannelT; typedef typename boost::gil::pixel_value_type<FloatChannelT, LayoutT>::type FloatPixelT; typedef typename boost::gil::type_from_x_iterator<FloatPixelT*>::view_t FloatViewT; FloatViewT tmp_glyph_view = boost::gil::interleaved_view( cellWidth(), cellHeight(), reinterpret_cast<FloatPixelT*>(ctx.imageData_.data()), cellWidth() * sizeof(FloatPixelT)); boost::gil::fill_pixels(tmp_glyph_view, FloatPixelT()); boost::gil::copy_and_convert_pixels(imgv, subimage_view( tmp_glyph_view, 0, 0, imgv.width(), imgv.height())); features()->project(ctx.imageData_, ctx.components_); return font()->getSymbol(features()->findClosestGlyph(ctx.components_)); }
void smart_blur_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; Imath::V2f stddev = get_value<Imath::V2f>( param( "stddev")); stddev = adjust_blur_size( stddev, context.subsample); copy_src_image( 0, area, ( blur_border_mode) get_value<int>( param( "border"))); blur_channels_mode channels = ( blur_channels_mode) get_value<int>( param( "channels")); switch( channels) { case channels_rgba: { image::buffer_t tmp( const_image_view().height(), const_image_view().width(), 4); image::smart_blur_rgba( const_image_view(), tmp.rgba_view(), image_view(), stddev.x, stddev.y, get_value<float>( param( "theresh"))); } break; case channels_rgb: { image::buffer_t tmp( const_image_view().height(), const_image_view().width(), 4); image::smart_blur_rgba( const_image_view(), tmp.rgba_view(), image_view(), stddev.x, stddev.y, get_value<float>( param( "theresh"))); boost::gil::fill_pixels( boost::gil::nth_channel_view( image_view(), 3), boost::gil::gray32f_pixel_t( 0)); boost::gil::copy_pixels( boost::gil::nth_channel_view( input_as<image_node_t>()->const_subimage_view( area), 3), boost::gil::nth_channel_view( subimage_view( area), 3)); } break; } }
void colorx_node_t::do_expression( const tbb::blocked_range<int>& range, const Imath::Box2i& area, const render::context_t& context) { std::string color_expr = get_value<std::string>( param( expr_param_name())); image_expression_t expr( color_expr, this, color_context); RAMEN_ASSERT( expr.isValid()); expr.setup_variables( this, context); image::const_image_view_t src = input_as<image_node_t>()->const_subimage_view( area); image::image_view_t dst = subimage_view( area); SeVec3d& cvar = expr.vec_vars["Cs"].val; double& avar = expr.vars["As"].val; double *out_avar = expr.get_local_var_ref( "Ao", &avar); for( int y = range.begin(); y < range.end(); ++y) { image::const_image_view_t::x_iterator src_it( src.row_begin( y)); image::image_view_t::x_iterator dst_it( dst.row_begin( y)); for( int x = 0, xe = src.width(); x < xe; ++x) { cvar[0] = boost::gil::get_color( *src_it, boost::gil::red_t()); cvar[1] = boost::gil::get_color( *src_it, boost::gil::green_t()); cvar[2] = boost::gil::get_color( *src_it, boost::gil::blue_t()); avar = boost::gil::get_color( *src_it, boost::gil::alpha_t()); SeVec3d result = expr.evaluate(); *dst_it++ = image::pixel_t( result[0], result[1], result[2], *out_avar); ++src_it; } } }
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); }
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 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)); }
TUTTLE_FORCEINLINE void fill_pixels( View& dstView, const OfxRectI& window, const typename View::value_type& pixelValue ) { typedef typename View::value_type Pixel; View dst = subimage_view( dstView, window.x1, window.y1, window.x2-window.x1, window.y2-window.y1 ); boost::gil::fill_pixels( dst, pixelValue ); }
void key_mix_layer_node_t::do_process( const render::context_t& context) { image_node_t *bg = input_as<image_node_t>( 0); image_node_t *fg = input_as<image_node_t>( 1); image_node_t *mt = input_as<image_node_t>( 2); Imath::Box2i bg_area = Imath::intersect( bg->defined(), defined()); if( !bg_area.isEmpty()) { render_input( 0, context); boost::gil::copy_pixels( bg->const_subimage_view( bg_area), subimage_view( bg_area)); release_input_image( 0); } Imath::Box2i comp_area( Imath::intersect( Imath::intersect( fg->defined(), mt->defined()), defined())); if( !comp_area.isEmpty()) { render_input( 1, context); // image buffer contains a shared ptr to // the actual pixels. Saving it to a local variable, // is equivalent to locking the pixels. // This could be improved, as I think it's not really clear. // There is also a lock method in buffer_t that it's // currently unused... image::buffer_t fg_img = fg->image(); render_input( 2, context); image::buffer_t alpha_img = mt->image(); boost::gil::tbb_transform3_pixels( const_subimage_view( comp_area), fg->const_subimage_view( comp_area), mt->const_subimage_view( comp_area), subimage_view( comp_area), key_mix_layer_mode_fun( get_value<float>( param( "opacity")))); release_input_image( 1); release_input_image( 2); } }
void invert_node_t::do_process( const render::context_t& context) { Imath::Box2i area( Imath::intersect( input_as<image_node_t>()->defined(), defined())); if( area.isEmpty()) return; if( get_value<int>( param( "channels"))) boost::gil::fill_pixels( image_view(), image::pixel_t( 0, 0, 0, 1)); do_process( input_as<image_node_t>()->const_subimage_view( area), subimage_view( area), context); }
void threadFunc() { ContextT context(matcher_->createContext()); //single character size size_t char_w = matcher_->cellWidth(); WorkItem wi = WorkItem(); while (queue_.wait_pop(wi)) { //processed image region size size_t roi_w = wi.imgv.width(); size_t roi_h = wi.imgv.height(); size_t x = 0, c = 0; for (; x + char_w <= roi_w; x += char_w, ++c) { wi.outp[c] = matcher_->match(context, subimage_view(wi.imgv, x, 0, char_w, roi_h)); } if (x < roi_w) { size_t dx = roi_w - x; wi.outp[c] = matcher_->match(context, subimage_view(wi.imgv, x, 0, dx, roi_h)); } queue_.done(); } }
void generate(const ViewT& imgv, TextSurface& text) { //single character size size_t char_w = matcher_->cellWidth(); size_t char_h = matcher_->cellHeight(); //text surface size size_t text_w = text.cols() * char_w; size_t text_h = text.rows() * char_h; //processed image region size size_t roi_w = std::min<size_t>(imgv.width(), text_w); size_t roi_h = std::min<size_t>(imgv.height(), text_h); size_t y = 0, r = 0; for (; y + char_h <= roi_h; y += char_h, ++r) { enqueue(subimage_view(imgv, 0, y, roi_w, char_h), text.row(r)); } if (y < roi_h) { size_t dy = roi_h - y; enqueue(subimage_view(imgv, 0, y, roi_w, dy), text.row(r)); } queue_.wait_empty(); }
rectangle<ptrdiff_t> operator()(In const& in, Out const& out) { auto const area = spatial_(in, out); typedef typename In::value_type InPixel; typedef typename Out::value_type OutPixel; BOOST_MPL_ASSERT_RELATION( boost::gil::size<OutPixel>::value,==,boost::gil::size<OutPixel>::value ); for_each_pixel( subimage_view(out, area), adjust_brightness_contrast<3>(chromatic_) ); return area; }
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 blur_channels_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; int iters = get_value<float>( param( "iters")); Imath::V2f r_radius = get_value<Imath::V2f>( param( "r_radius")) / iters; Imath::V2f g_radius = get_value<Imath::V2f>( param( "g_radius")) / iters; Imath::V2f b_radius = get_value<Imath::V2f>( param( "b_radius")) / iters; Imath::V2f a_radius = get_value<Imath::V2f>( param( "a_radius")) / iters; r_radius = adjust_blur_size( r_radius, context.subsample); g_radius = adjust_blur_size( g_radius, context.subsample); b_radius = adjust_blur_size( b_radius, context.subsample); a_radius = adjust_blur_size( a_radius, context.subsample); boost::gil::copy_pixels( input_as<image_node_t>()->const_subimage_view( area), subimage_view( area)); image::buffer_t buffer( image_view().height(), image_view().width(), 1); image::gray_image_view_t tmp = buffer.gray_view(); blur_border_mode bmode = ( blur_border_mode) get_value<int>( param( "border")); boost::gil::fill_pixels( tmp, 0.0f); blur_channel( 0, area, tmp, r_radius, iters, bmode); boost::gil::fill_pixels( tmp, 0.0f); blur_channel( 1, area, tmp, g_radius, iters, bmode); boost::gil::fill_pixels( tmp, 0.0f); blur_channel( 2, area, tmp, b_radius, iters, bmode); boost::gil::fill_pixels( tmp, 0.0f); blur_channel( 3, area, tmp, a_radius, iters, bmode); }
void layer_node_t::do_process_mult_min_overlay_mix( const render::context_t& context) { image_node_t *bg = input_as<image_node_t>( 0); image_node_t *fg = input_as<image_node_t>( 1); int mode = get_value<int>( param( "layer_mode")); float opacity = get_value<float>( param( "opacity")); Imath::Box2i bg_area( ImathExt::intersect( bg->defined(), defined())); Imath::Box2i comp_area( ImathExt::intersect( fg->defined(), defined())); if( !bg_area.isEmpty()) { render_input( 0, context); if( opacity == 0.0f) // just copy the background and return { boost::gil::copy_pixels( bg->const_subimage_view( bg_area), subimage_view( bg_area)); return; } if( mode == comp_overlay) { image::composite_zero_overlay( bg->const_subimage_view( bg_area), subimage_view( bg_area), opacity); Imath::Box2i common_area( ImathExt::intersect( fg->defined(), bg->defined())); if( !common_area.isEmpty()) boost::gil::copy_pixels( bg->const_subimage_view( common_area), subimage_view( common_area)); } else { if( opacity == 1.0f) // the normal case, nothing special to do boost::gil::copy_pixels( bg->const_subimage_view( bg_area), subimage_view( bg_area)); else // we need to handle the areas of the bg that don't intersect the fg { image::mul_image_scalar( bg->const_subimage_view( bg_area), 1.0f - opacity, subimage_view( bg_area)); Imath::Box2i common_area( ImathExt::intersect( fg->defined(), bg->defined())); if( !common_area.isEmpty()) boost::gil::copy_pixels( bg->const_subimage_view( common_area), subimage_view( common_area)); } } // we don't need the bg anymore release_input_image( 0); } if( !comp_area.isEmpty()) { render_input( 1, context); switch( mode) { case comp_min: image::composite_min( const_subimage_view( comp_area), input_as<image_node_t>( 1)->const_subimage_view( comp_area), subimage_view( comp_area), opacity); break; case comp_mult: image::composite_mul( const_subimage_view( comp_area), input_as<image_node_t>( 1)->const_subimage_view( comp_area), subimage_view( comp_area), opacity); break; case comp_mix: image::composite_mix( const_subimage_view( comp_area), input_as<image_node_t>( 1)->const_subimage_view( comp_area), subimage_view( comp_area), opacity); break; case comp_overlay: image::composite_overlay( const_subimage_view( comp_area), input_as<image_node_t>( 1)->const_subimage_view( comp_area), subimage_view( comp_area), opacity); break; } release_input_image( 1); } }
void layer_node_t::do_process( const render::context_t& context) { int mode = get_value<int>( param( "layer_mode")); if( mode == comp_mult || mode == comp_min || mode == comp_overlay || mode == comp_mix) // min, mult and overlay are special { do_process_mult_min_overlay_mix( context); return; } image_node_t *bg = input_as<image_node_t>( 0); image_node_t *fg = input_as<image_node_t>( 1); Imath::Box2i bg_area = ImathExt::intersect( bg->defined(), defined()); float opacity = get_value<float>( param( "opacity")); if( !bg_area.isEmpty()) { render_input( 0, context); boost::gil::copy_pixels( bg->const_subimage_view( bg_area), subimage_view( bg_area)); release_input_image( 0); } Imath::Box2i comp_area( ImathExt::intersect( fg->defined(), defined())); if( !comp_area.isEmpty()) { if( opacity == 0.0f) return; render_input( 1, context); switch( mode) { case comp_over: image::composite_over( const_subimage_view( comp_area), input_as<image_node_t>( 1)->const_subimage_view( comp_area), subimage_view( comp_area), opacity); break; case comp_add: image::composite_add( const_subimage_view( comp_area), input_as<image_node_t>( 1)->const_subimage_view( comp_area), subimage_view( comp_area), opacity); break; case comp_sub: image::composite_sub( const_subimage_view( comp_area), input_as<image_node_t>( 1)->const_subimage_view( comp_area), subimage_view( comp_area), opacity); break; case comp_screen: image::composite_screen( const_subimage_view( comp_area), input_as<image_node_t>( 1)->const_subimage_view( comp_area), subimage_view( comp_area), opacity); break; case comp_overlay: image::composite_overlay( const_subimage_view( comp_area), input_as<image_node_t>( 1)->const_subimage_view( comp_area), subimage_view( comp_area), opacity); break; case comp_diff: image::composite_diff( const_subimage_view( comp_area), input_as<image_node_t>( 1)->const_subimage_view( comp_area), subimage_view( comp_area), opacity); break; case comp_max: image::composite_max( const_subimage_view( comp_area), input_as<image_node_t>( 1)->const_subimage_view( comp_area), subimage_view( comp_area), opacity); break; } release_input_image( 1); } }
template <typename View> result_type operator()(const View& src) const { return result_type(subimage_view(src,_topleft,_size2)); }