Exemple #1
0
bool THRawBitmap::_checkScaled(THRenderTarget* pCanvas, SDL_Rect& rcDest)
{
    float fFactor;
    if(!pCanvas->shouldScaleBitmaps(&fFactor))
        return false;
    int iScaledWidth = (int)((float)m_pBitmap->w * fFactor);
    if(!m_pCachedScaledBitmap || m_pCachedScaledBitmap->w != iScaledWidth)
    {
        SDL_FreeSurface(m_pCachedScaledBitmap);
        Uint32 iRMask, iGMask, iBMask;
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
        iRMask = 0xff000000;
        iGMask = 0x00ff0000;
        iBMask = 0x0000ff00;
#else
        iRMask = 0x000000ff;
        iGMask = 0x0000ff00;
        iBMask = 0x00ff0000;
#endif

        m_pCachedScaledBitmap = SDL_CreateRGBSurface(SDL_SWSURFACE, iScaledWidth, (int)((float)m_pBitmap->h * fFactor), 24, iRMask, iGMask, iBMask, 0);
        SDL_LockSurface(m_pCachedScaledBitmap);
        SDL_LockSurface(m_pBitmap);

        typedef agg::pixfmt_rgb24_pre pixfmt_pre_t;
        typedef agg::renderer_base<pixfmt_pre_t> renbase_pre_t;
        typedef image_accessor_clip_rgb24_pal8<pixfmt_pre_t> imgsrc_t;
        typedef agg::span_interpolator_linear<> interpolator_t;
        typedef agg::span_image_filter_rgb_2x2<imgsrc_t, interpolator_t> span_gen_type;
        agg::scanline_p8 sl;
        agg::span_allocator<pixfmt_pre_t::color_type> sa;
        agg::image_filter<agg::image_filter_bilinear> filter;
        agg::trans_affine_scaling img_mtx(1.0 / fFactor);
        agg::rendering_buffer rbuf_src(m_pData, m_pBitmap->w, m_pBitmap->h, m_pBitmap->pitch);
        imgsrc_t img_src(rbuf_src, *m_pPalette, agg::rgba(0.0, 0.0, 0.0));
        interpolator_t interpolator(img_mtx);
        span_gen_type sg(img_src, interpolator, filter);
        agg::rendering_buffer rbuf(reinterpret_cast<unsigned char*>(m_pCachedScaledBitmap->pixels), m_pCachedScaledBitmap->w, m_pCachedScaledBitmap->h, m_pCachedScaledBitmap->pitch);
        pixfmt_pre_t pixf_pre(rbuf);
        renbase_pre_t rbase_pre(pixf_pre);
        rasterizer_scanline_rect ras(0, 0, rbuf.width(), rbuf.height());
        rbase_pre.clear(agg::rgba(1.0,0,0,0));
        agg::render_scanlines_aa(ras, sl, rbase_pre, sa, sg);

        SDL_UnlockSurface(m_pBitmap);
        SDL_UnlockSurface(m_pCachedScaledBitmap);
    }
    rcDest.x = (Sint16)((float)rcDest.x * fFactor);
    rcDest.y = (Sint16)((float)rcDest.y * fFactor);
    return true;
}
Exemple #2
0
int agg2RenderPolygonTiled(imageObj *img, shapeObj *p, imageObj * tile)
{
  assert(img->format->renderer == tile->format->renderer);

  AGG2Renderer *r = AGG_RENDERER(img);
  AGG2Renderer *tileRenderer = AGG_RENDERER(tile);
  polygon_adaptor polygons(p);
  typedef mapserver::wrap_mode_repeat wrap_type;
  typedef mapserver::image_accessor_wrap<pixel_format,wrap_type,wrap_type> img_source_type;
  typedef mapserver::span_pattern_rgba<img_source_type> span_gen_type;
  mapserver::span_allocator<mapserver::rgba8> sa;
  r->m_rasterizer_aa.reset();
  r->m_rasterizer_aa.filling_rule(mapserver::fill_even_odd);
  img_source_type img_src(tileRenderer->m_pixel_format);
  span_gen_type sg(img_src, 0, 0);
  r->m_rasterizer_aa.add_path(polygons);
  mapserver::render_scanlines_aa(r->m_rasterizer_aa, r->sl_poly, r->m_renderer_base, sa , sg);
  return MS_SUCCESS;
}
    void render(mapnik::image_rgba8 const& image) const
    {
        agg::rendering_buffer buf(current_buffer_.bytes(), current_buffer_.width(),
                                  current_buffer_.height(), current_buffer_.row_size());
        ras_ptr_->reset();
        value_double gamma = get<value_double, keys::gamma>(sym_, feature_, common_.vars_);
        gamma_method_enum gamma_method = get<gamma_method_enum, keys::gamma_method>(sym_, feature_, common_.vars_);
        if (gamma != gamma_ || gamma_method != gamma_method_)
        {
            set_gamma_method(ras_ptr_, gamma, gamma_method);
            gamma_method_ = gamma_method;
            gamma_ = gamma;
        }

        using vertex_converter_type = vertex_converter<clip_poly_tag,
                                                       transform_tag,
                                                       affine_transform_tag,
                                                       simplify_tag,
                                                       smooth_tag>;
        using pattern_type = agg_polygon_pattern<vertex_converter_type>;

        pattern_type pattern(image, common_, sym_, feature_, prj_trans_);

        pattern_type::pixfmt_type pixf(buf);
        pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym_, feature_, common_.vars_)));
        pattern_type::renderer_base renb(pixf);

        unsigned w = image.width();
        unsigned h = image.height();
        agg::rendering_buffer pattern_rbuf((agg::int8u*)image.bytes(),w,h,w*4);
        agg::pixfmt_rgba32_pre pixf_pattern(pattern_rbuf);
        pattern_type::img_source_type img_src(pixf_pattern);

        if (prj_trans_.equal() && pattern.clip_) pattern.converter_.set<clip_poly_tag>();

        ras_ptr_->filling_rule(agg::fill_even_odd);

        pattern.render(renb, *ras_ptr_);
    }
Exemple #4
0
void agg_renderer<T0,T1>::process(polygon_pattern_symbolizer const& sym,
                                  mapnik::feature_impl & feature,
                                  proj_transform const& prj_trans)
{
    std::string filename = get<std::string, keys::file>(sym, feature, common_.vars_);
    if (filename.empty()) return;
    std::shared_ptr<mapnik::marker const> marker = marker_cache::instance().find(filename, true);

    buffer_type & current_buffer = buffers_.top().get();
    agg::rendering_buffer buf(current_buffer.bytes(), current_buffer.width(),
                              current_buffer.height(), current_buffer.row_size());
    ras_ptr->reset();
    value_double gamma = get<value_double, keys::gamma>(sym, feature, common_.vars_);
    gamma_method_enum gamma_method = get<gamma_method_enum, keys::gamma_method>(sym, feature, common_.vars_);
    if (gamma != gamma_ || gamma_method != gamma_method_)
    {
        set_gamma_method(ras_ptr, gamma, gamma_method);
        gamma_method_ = gamma_method;
        gamma_ = gamma;
    }

    value_bool clip = get<value_bool, keys::clip>(sym, feature, common_.vars_);
    value_double opacity = get<double, keys::opacity>(sym, feature, common_.vars_);
    value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym, feature, common_.vars_);
    value_double smooth = get<value_double, keys::smooth>(sym, feature, common_.vars_);

    using color = agg::rgba8;
    using order = agg::order_rgba;
    using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
    using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;

    using wrap_x_type = agg::wrap_mode_repeat;
    using wrap_y_type = agg::wrap_mode_repeat;
    using img_source_type = agg::image_accessor_wrap<agg::pixfmt_rgba32_pre,
                                                     wrap_x_type,
                                                     wrap_y_type>;

    using span_gen_type = agg::span_pattern_rgba<img_source_type>;
    using ren_base = agg::renderer_base<pixfmt_type>;

    using renderer_type = agg::renderer_scanline_aa_alpha<ren_base,
                                                          agg::span_allocator<agg::rgba8>,
                                                          span_gen_type>;

    pixfmt_type pixf(buf);
    pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym, feature, common_.vars_)));
    ren_base renb(pixf);

    common_pattern_process_visitor<polygon_pattern_symbolizer, rasterizer> visitor(*ras_ptr, common_, sym, feature);
    image_rgba8 image(util::apply_visitor(visitor, *marker));

    unsigned w = image.width();
    unsigned h = image.height();
    agg::rendering_buffer pattern_rbuf((agg::int8u*)image.bytes(),w,h,w*4);
    agg::pixfmt_rgba32_pre pixf_pattern(pattern_rbuf);
    img_source_type img_src(pixf_pattern);

    box2d<double> clip_box = clipping_extent(common_);
    coord<unsigned, 2> offset(detail::offset(sym, feature, prj_trans, common_, clip_box));
    span_gen_type sg(img_src, offset.x, offset.y);

    agg::span_allocator<agg::rgba8> sa;
    renderer_type rp(renb,sa, sg, unsigned(opacity * 255));

    agg::trans_affine tr;
    auto transform = get_optional<transform_type>(sym, keys::geometry_transform);
    if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_);
    using vertex_converter_type = vertex_converter<clip_poly_tag,
                                                   transform_tag,
                                                   affine_transform_tag,
                                                   simplify_tag,
                                                   smooth_tag>;

    vertex_converter_type converter(clip_box, sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_);

    if (prj_trans.equal() && clip) converter.set<clip_poly_tag>();
    converter.set<transform_tag>(); //always transform
    converter.set<affine_transform_tag>(); // optional affine transform
    if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
    if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter

    using apply_vertex_converter_type = detail::apply_vertex_converter<vertex_converter_type, rasterizer>;
    using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>;
    apply_vertex_converter_type apply(converter, *ras_ptr);
    mapnik::util::apply_visitor(vertex_processor_type(apply),feature.get_geometry());
    agg::scanline_u8 sl;
    ras_ptr->filling_rule(agg::fill_even_odd);
    agg::render_scanlines(*ras_ptr, sl, rp);
}
Exemple #5
0
    virtual void on_draw()
    {
        typedef agg::renderer_base<pixfmt>     renderer_base;
        typedef agg::renderer_base<pixfmt_pre> renderer_base_pre;

        pixfmt            pixf(rbuf_window());
        pixfmt_pre        pixf_pre(rbuf_window());
        renderer_base     rb(pixf);
        renderer_base_pre rb_pre(pixf_pre);

        rb.clear(agg::rgba(1.0, 1.0, 1.0));

        agg::trans_affine src_mtx;
        src_mtx *= agg::trans_affine_translation(-initial_width()/2 - 10, -initial_height()/2 - 20 - 10);
        src_mtx *= agg::trans_affine_rotation(m_angle.value() * agg::pi / 180.0);
        src_mtx *= agg::trans_affine_scaling(m_scale.value());
        src_mtx *= agg::trans_affine_translation(initial_width()/2, initial_height()/2 + 20);
        src_mtx *= trans_affine_resizing();

        agg::trans_affine img_mtx;
        img_mtx *= agg::trans_affine_translation(-initial_width()/2 + 10, -initial_height()/2 + 20 + 10);
        img_mtx *= agg::trans_affine_rotation(m_angle.value() * agg::pi / 180.0);
        img_mtx *= agg::trans_affine_scaling(m_scale.value());
        img_mtx *= agg::trans_affine_translation(initial_width()/2, initial_height()/2 + 20);
        img_mtx *= trans_affine_resizing();
        img_mtx.invert();

        agg::span_allocator<color_type> sa;

        typedef agg::span_interpolator_linear<> interpolator_type;
        interpolator_type interpolator(img_mtx);

        typedef agg::image_accessor_clip<pixfmt> img_source_type;

        pixfmt img_pixf(rbuf_img(0));
        img_source_type img_src(img_pixf, agg::rgba_pre(0, 0.4, 0, 0.5));

        /*
                // Version without filtering (nearest neighbor)
                //------------------------------------------
                typedef agg::span_image_filter_rgb_nn<img_source_type,
                                                      interpolator_type> span_gen_type;
                span_gen_type sg(img_src, interpolator);
                //------------------------------------------
        */

        // Version with "hardcoded" bilinear filter and without
        // image_accessor (direct filter, the old variant)
        //------------------------------------------
        typedef agg::span_image_filter_rgb_bilinear_clip<pixfmt,
                interpolator_type> span_gen_type;
        span_gen_type sg(img_pixf, agg::rgba_pre(0, 0.4, 0, 0.5), interpolator);
        //------------------------------------------

        /*
                // Version with arbitrary 2x2 filter
                //------------------------------------------
                typedef agg::span_image_filter_rgb_2x2<img_source_type,
                                                       interpolator_type> span_gen_type;
                agg::image_filter<agg::image_filter_kaiser> filter;
                span_gen_type sg(img_src, interpolator, filter);
                //------------------------------------------
        */
        /*
                // Version with arbitrary filter
                //------------------------------------------
                typedef agg::span_image_filter_rgb<img_source_type,
                                                   interpolator_type> span_gen_type;
                agg::image_filter<agg::image_filter_spline36> filter;
                span_gen_type sg(img_src, interpolator, filter);
                //------------------------------------------
        */

        agg::rasterizer_scanline_aa<> ras;
        ras.clip_box(0, 0, width(), height());
        agg::scanline_u8 sl;
        double r = initial_width();
        if(initial_height() - 60 < r) r = initial_height() - 60;
        agg::ellipse ell(initial_width()  / 2.0 + 10,
                         initial_height() / 2.0 + 20 + 10,
                         r / 2.0 + 16.0,
                         r / 2.0 + 16.0, 200);


        agg::conv_transform<agg::ellipse> tr(ell, src_mtx);

        ras.add_path(tr);
        agg::render_scanlines_aa(ras, sl, rb_pre, sa, sg);

        agg::render_ctrl(ras, sl, rb, m_angle);
        agg::render_ctrl(ras, sl, rb, m_scale);
    }
Exemple #6
0
void scale_image_agg(T & target, T const& source, scaling_method_e scaling_method,
                     double image_ratio_x, double image_ratio_y, double x_off_f, double y_off_f,
                     double filter_factor)
{
    // "the image filters should work namely in the premultiplied color space"
    // http://old.nabble.com/Re:--AGG--Basic-image-transformations-p1110665.html
    // "Yes, you need to use premultiplied images only. Only in this case the simple weighted averaging works correctly in the image fitering."
    // http://permalink.gmane.org/gmane.comp.graphics.agg/3443
    using image_type = T;
    using pixel_type = typename image_type::pixel_type;
    using pixfmt_pre = typename detail::agg_scaling_traits<image_type>::pixfmt_pre;
    using color_type = typename detail::agg_scaling_traits<image_type>::color_type;
    using img_src_type = typename detail::agg_scaling_traits<image_type>::img_src_type;
    using interpolator_type = typename detail::agg_scaling_traits<image_type>::interpolator_type;
    using renderer_base_pre = agg::renderer_base<pixfmt_pre>;
    constexpr std::size_t pixel_size = sizeof(pixel_type);

    // define some stuff we'll use soon
    agg::rasterizer_scanline_aa<> ras;
    agg::scanline_u8 sl;
    agg::span_allocator<color_type> sa;

    // initialize source AGG buffer
    agg::rendering_buffer rbuf_src(const_cast<unsigned char*>(source.bytes()),
                                   source.width(), source.height(), source.width() * pixel_size);
    pixfmt_pre pixf_src(rbuf_src);

    img_src_type img_src(pixf_src);

    // initialize destination AGG buffer (with transparency)
    agg::rendering_buffer rbuf_dst(target.bytes(), target.width(), target.height(), target.width() * pixel_size);
    pixfmt_pre pixf_dst(rbuf_dst);
    renderer_base_pre rb_dst_pre(pixf_dst);

    // create a scaling matrix
    agg::trans_affine img_mtx;
    img_mtx /= agg::trans_affine_scaling(image_ratio_x, image_ratio_y);

    // create a linear interpolator for our scaling matrix
    interpolator_type interpolator(img_mtx);
    // draw an anticlockwise polygon to render our image into
    double scaled_width = target.width();
    double scaled_height = target.height();
    ras.reset();
    ras.move_to_d(x_off_f,                y_off_f);
    ras.line_to_d(x_off_f + scaled_width, y_off_f);
    ras.line_to_d(x_off_f + scaled_width, y_off_f + scaled_height);
    ras.line_to_d(x_off_f,                y_off_f + scaled_height);

    if (scaling_method == SCALING_NEAR)
    {
        using span_gen_type = typename detail::agg_scaling_traits<image_type>::span_image_filter;
        span_gen_type sg(img_src, interpolator);
        agg::render_scanlines_aa(ras, sl, rb_dst_pre, sa, sg);
    }
    else
    {
        using span_gen_type = typename detail::agg_scaling_traits<image_type>::span_image_resample_affine;
        agg::image_filter_lut filter;
        detail::set_scaling_method(filter, scaling_method, filter_factor);
        span_gen_type sg(img_src, interpolator, filter);
        agg::render_scanlines_aa(ras, sl, rb_dst_pre, sa, sg);
    }

}
    virtual void on_draw()
    {
        typedef agg::pixfmt_bgr24 pixfmt;
        typedef agg::renderer_base<pixfmt> renderer_base;

        pixfmt pixf(rbuf_window());
        renderer_base rb(pixf);

        rb.clear(agg::rgba(1.0, 1.0, 1.0));

        agg::trans_affine src_mtx;
        src_mtx *= agg::trans_affine_translation(-initial_width()/2, -initial_height()/2);
        src_mtx *= agg::trans_affine_rotation(10.0 * agg::pi / 180.0);
        src_mtx *= agg::trans_affine_translation(initial_width()/2, initial_height()/2);
        src_mtx *= trans_affine_resizing();

        agg::trans_affine img_mtx = src_mtx;
        img_mtx.invert();

        typedef agg::span_allocator<agg::rgba8> span_alloc;

        unsigned i;

        unsigned char brightness_alpha_array[agg::span_conv_brightness_alpha_rgb8::array_size];
        for(i = 0; i < agg::span_conv_brightness_alpha_rgb8::array_size; i++)
        {
            brightness_alpha_array[i] = 
                agg::int8u(m_alpha.value(double(i) / 
                         double(agg::span_conv_brightness_alpha_rgb8::array_size)) * 255.0);
        }
        agg::span_conv_brightness_alpha_rgb8 color_alpha(brightness_alpha_array);



        typedef agg::image_accessor_clip<pixfmt> img_source_type;
        typedef agg::span_interpolator_linear<> interpolator_type; 
        typedef agg::span_image_filter_rgb_bilinear<img_source_type,
                                                    interpolator_type> span_gen;
        typedef agg::span_converter<span_gen,
                                    agg::span_conv_brightness_alpha_rgb8> span_conv;


        span_alloc sa;
        interpolator_type interpolator(img_mtx);
        pixfmt img_pixf(rbuf_img(0));
        img_source_type img_src(img_pixf, agg::rgba(0,0,0,0));
        span_gen sg(img_src, interpolator);
        span_conv sc(sg, color_alpha);
        agg::ellipse ell;
        agg::rasterizer_scanline_aa<> ras;
        agg::scanline_u8 sl;
        
        for(i = 0; i < 50; i++)
        {
            ell.init(m_x[i], m_y[i], m_rx[i], m_ry[i], 50);
            ras.add_path(ell);
            agg::render_scanlines_aa_solid(ras, sl, rb, m_colors[i]);
        }


        ell.init(initial_width()  / 2.0, 
                 initial_height() / 2.0, 
                 initial_width()  / 1.9, 
                 initial_height() / 1.9, 200);


        agg::conv_transform<agg::ellipse> tr(ell, src_mtx);


        ras.add_path(tr);
        agg::render_scanlines_aa(ras, sl, rb, sa, sc);

        agg::render_ctrl(ras, sl, rb, m_alpha);
    }
void agg_renderer<T>::process(polygon_pattern_symbolizer const& sym,
                              mapnik::feature_ptr const& feature,
                              proj_transform const& prj_trans)
{
    typedef agg::conv_clip_polygon<geometry_type> clipped_geometry_type;
    typedef coord_transform2<CoordTransform,clipped_geometry_type> path_type;
    typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;
    typedef agg::wrap_mode_repeat wrap_x_type;
    typedef agg::wrap_mode_repeat wrap_y_type;
    typedef agg::pixfmt_alpha_blend_rgba<agg::blender_rgba32_plain,
        agg::row_accessor<agg::int8u>, agg::pixel32_type> rendering_buffer;
    typedef agg::image_accessor_wrap<rendering_buffer,
        wrap_x_type,
        wrap_y_type> img_source_type;

    typedef agg::span_pattern_rgba<img_source_type> span_gen_type;

    typedef agg::renderer_scanline_aa<ren_base,
        agg::span_allocator<agg::rgba8>,
        span_gen_type> renderer_type;


    agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
    agg::pixfmt_rgba32_plain pixf(buf);
    ren_base renb(pixf);

    agg::scanline_u8 sl;
    ras_ptr->reset();
    set_gamma_method(sym,ras_ptr);

    std::string filename = path_processor_type::evaluate( *sym.get_filename(), *feature);
    boost::optional<mapnik::marker_ptr> marker;
    if ( !filename.empty() )
    {
        marker = marker_cache::instance()->find(filename, true);
    }
    else
    {
        std::clog << "### Warning: file not found: " << filename << "\n";
    }

    if (!marker) return;

    if (!(*marker)->is_bitmap())
    {
        std::clog << "### Warning only images (not '" << filename << "') are supported in the polygon_pattern_symbolizer\n";
        return;
    }


    boost::optional<image_ptr> pat = (*marker)->get_bitmap_data();

    if (!pat) return;

    unsigned w=(*pat)->width();
    unsigned h=(*pat)->height();
    agg::row_accessor<agg::int8u> pattern_rbuf((agg::int8u*)(*pat)->getBytes(),w,h,w*4);
    agg::span_allocator<agg::rgba8> sa;
    agg::pixfmt_alpha_blend_rgba<agg::blender_rgba32_plain,
        agg::row_accessor<agg::int8u>, agg::pixel32_type> pixf_pattern(pattern_rbuf);
    img_source_type img_src(pixf_pattern);

    unsigned num_geometries = feature->num_geometries();

    pattern_alignment_e align = sym.get_alignment();
    unsigned offset_x=0;
    unsigned offset_y=0;

    if (align == LOCAL_ALIGNMENT)
    {
        double x0=0,y0=0;
        if (num_geometries>0) // FIXME: hmm...?
        {
            clipped_geometry_type clipped(feature->get_geometry(0));
            clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy());
            path_type path(t_,clipped,prj_trans);
            path.vertex(&x0,&y0);
        }
        offset_x = unsigned(width_-x0);
        offset_y = unsigned(height_-y0);
    }

    span_gen_type sg(img_src, offset_x, offset_y);
    renderer_type rp(renb,sa, sg);
    //metawriter_with_properties writer = sym.get_metawriter();
    for (unsigned i=0;i<num_geometries;++i)
    {
        geometry_type & geom = feature->get_geometry(i);
        if (geom.num_points() > 2)
        {
            clipped_geometry_type clipped(geom);
            clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy());
            path_type path(t_,clipped,prj_trans);
            ras_ptr->add_path(path);
            //if (writer.first) writer.first->add_polygon(path, *feature, t_, writer.second);
        }
    }
    agg::render_scanlines(*ras_ptr, sl, rp);
}
Exemple #9
0
    //------------------------------------------------------------------------
    virtual void on_draw()
    {
        double width = rbuf_window().width();
        double height = rbuf_window().height();
    
        typedef agg::renderer_base<pixfmt>     renderer_base;
        typedef agg::renderer_base<pixfmt_pre> renderer_base_pre;
       
        pixfmt     pixf(rbuf_window());
        pixfmt_pre pixf_pre(rbuf_window());

        renderer_base     rb(pixf);
        renderer_base_pre rb_pre(pixf_pre);

        rb.clear(agg::rgba(1.0, 1.0, 1.0));

        agg::trans_affine polygon_mtx;

        polygon_mtx *= agg::trans_affine_translation(-m_polygon_cx, -m_polygon_cy);
        polygon_mtx *= agg::trans_affine_rotation(m_polygon_angle.value() * agg::pi / 180.0);
        polygon_mtx *= agg::trans_affine_scaling(m_polygon_scale.value());
        polygon_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy);

        double r = initial_width() / 3.0 - 8.0;
        create_star(m_polygon_cx, m_polygon_cy, r, r / 1.45, 14);

        agg::conv_transform<agg::path_storage> tr(m_ps, polygon_mtx);

        typedef agg::wrap_mode_reflect_auto_pow2 wrap_x_type;
        typedef agg::wrap_mode_reflect_auto_pow2 wrap_y_type;
        typedef agg::image_accessor_wrap<pixfmt, 
                                         wrap_x_type,
                                         wrap_y_type> img_source_type;
        typedef agg::span_pattern_rgba<img_source_type> span_gen_type;

        unsigned offset_x = 0;
        unsigned offset_y = 0;

        if(m_tie_pattern.status())
        {
            offset_x = unsigned(width-m_polygon_cx);
            offset_y = unsigned(height-m_polygon_cy);
        }

        agg::span_allocator<color_type> sa;
        pixfmt          img_pixf(m_pattern_rbuf);
        img_source_type img_src(img_pixf);
        span_gen_type sg(img_src, offset_x, offset_y);

        // Alpha is meaningful for RGB only because RGBA has its own
        sg.alpha(span_gen_type::value_type(m_pattern_alpha.value() * 255.0)); 

        m_ras.add_path(tr);
        agg::render_scanlines_aa(m_ras, m_sl, rb_pre, sa, sg);

        agg::render_ctrl(m_ras, m_sl, rb, m_polygon_angle);
        agg::render_ctrl(m_ras, m_sl, rb, m_polygon_scale);
        agg::render_ctrl(m_ras, m_sl, rb, m_pattern_angle);
        agg::render_ctrl(m_ras, m_sl, rb, m_pattern_size);
        agg::render_ctrl(m_ras, m_sl, rb, m_pattern_alpha);
        agg::render_ctrl(m_ras, m_sl, rb, m_rotate_polygon);
        agg::render_ctrl(m_ras, m_sl, rb, m_rotate_pattern);
        agg::render_ctrl(m_ras, m_sl, rb, m_tie_pattern);
    }
    virtual void on_draw()
    {
        pixfmt            pixf(rbuf_window());
        pixfmt_pre        pixf_pre(rbuf_window());
        renderer_base     rb(pixf);
        renderer_base_pre rb_pre(pixf_pre);

        if(!m_test_flag)
        {
            rb.clear(agg::rgba(1, 1, 1));
        }

        if(m_trans_type.cur_item() == 0)
        {
            // For the affine parallelogram transformations we
            // calculate the 4-th (implicit) point of the parallelogram
            m_quad.xn(3) = m_quad.xn(0) + (m_quad.xn(2) - m_quad.xn(1));
            m_quad.yn(3) = m_quad.yn(0) + (m_quad.yn(2) - m_quad.yn(1));
        }

        if(!m_test_flag)
        {
            //--------------------------
            // Render the "quad" tool and controls
            g_rasterizer.add_path(m_quad);
            agg::render_scanlines_aa_solid(g_rasterizer, g_scanline, rb, agg::rgba(0, 0.3, 0.5, 0.6));

            //--------------------------
            agg::render_ctrl(g_rasterizer, g_scanline, rb, m_trans_type);
        }

        // Prepare the polygon to rasterize. Here we need to fill
        // the destination (transformed) polygon.
        g_rasterizer.clip_box(0, 0, width(), height());
        g_rasterizer.reset();
        g_rasterizer.move_to_d(m_quad.xn(0), m_quad.yn(0));
        g_rasterizer.line_to_d(m_quad.xn(1), m_quad.yn(1));
        g_rasterizer.line_to_d(m_quad.xn(2), m_quad.yn(2));
        g_rasterizer.line_to_d(m_quad.xn(3), m_quad.yn(3));


        typedef agg::span_allocator<color_type> span_alloc_type;
        span_alloc_type sa;
        agg::image_filter<agg::image_filter_hanning> filter;
    
        typedef agg::wrap_mode_reflect_auto_pow2 remainder_type;
        typedef agg::image_accessor_wrap<pixfmt, 
                                         remainder_type, 
                                         remainder_type> img_source_type;

        pixfmt img_pixf(rbuf_img(0));
        img_source_type img_src(img_pixf);

        enum subdiv_shift_e { subdiv_shift = 2 };
         
        switch(m_trans_type.cur_item())
        {
            case 0:
            {
                // Note that we consruct an affine matrix that transforms
                // a parallelogram to a rectangle, i.e., it's inverted.
                // It's actually the same as:
                // tr(g_x1, g_y1, g_x2, g_y2, m_triangle.polygon());
                // tr.invert();
                agg::trans_affine tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2);

                // Also note that we can use the linear interpolator instead of 
                // arbitrary span_interpolator_trans. It works much faster, 
                // but the transformations must be linear and parellel.
                typedef agg::span_interpolator_linear<agg::trans_affine> interpolator_type;
                interpolator_type interpolator(tr);

                typedef span_image_filter_2x2<img_source_type,
                                              interpolator_type> span_gen_type;
                span_gen_type sg(img_src, interpolator, filter);
                agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg);
                break;
            }

            case 1:
            {
                agg::trans_bilinear tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2);
                if(tr.is_valid())
                {
                    typedef agg::span_interpolator_linear<agg::trans_bilinear> interpolator_type;
                    interpolator_type interpolator(tr);

                    typedef span_image_filter_2x2<img_source_type,
                                                  interpolator_type> span_gen_type;
                    span_gen_type sg(img_src, interpolator, filter);
                    agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg);
                }
                break;
            }

            case 2:
            {
                agg::trans_perspective tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2);
                if(tr.is_valid())
                {
                    typedef agg::span_interpolator_linear_subdiv<agg::trans_perspective, 8> interpolator_type;
                    interpolator_type interpolator(tr);

                    typedef span_image_filter_2x2<img_source_type,
                                                  interpolator_type> span_gen_type;
                    span_gen_type sg(img_src, interpolator, filter);
                    agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg);
                }
                break;
            }
        }
    }
    virtual void on_draw()
    {
        double img_width = rbuf_img(0).width();
        double img_height = rbuf_img(0).height();
    
        typedef agg::pixfmt_bgr24 pixfmt; 
        typedef agg::renderer_base<pixfmt> renderer_base;

        pixfmt pixf(rbuf_window());
        pixfmt img_pixf(rbuf_img(0));

        renderer_base rb(pixf);

        rb.clear(agg::rgba(1.0, 1.0, 1.0));

        agg::trans_affine src_mtx;
        src_mtx *= agg::trans_affine_translation(-img_width/2, -img_height/2);
        src_mtx *= agg::trans_affine_rotation(m_angle.value() * agg::pi / 180.0);
        src_mtx *= agg::trans_affine_translation(img_width/2 + 10, img_height/2 + 10 + 40);
        src_mtx *= trans_affine_resizing();

        agg::trans_affine img_mtx;
        img_mtx *= agg::trans_affine_translation(-img_width/2, -img_height/2);
        img_mtx *= agg::trans_affine_rotation(m_angle.value() * agg::pi / 180.0);
        img_mtx *= agg::trans_affine_scaling(m_scale.value());
        img_mtx *= agg::trans_affine_translation(img_width/2 + 10, img_height/2 + 10 + 40);
        img_mtx *= trans_affine_resizing();
        img_mtx.invert();


        typedef agg::span_allocator<agg::rgba8> span_alloc_type;

        span_alloc_type sa;
        
        typedef agg::span_interpolator_adaptor<agg::span_interpolator_linear<>, 
                                               periodic_distortion> interpolator_type;

        periodic_distortion*  dist = 0;
        distortion_wave       dist_wave;
        distortion_swirl      dist_swirl;
        distortion_wave_swirl dist_wave_swirl;
        distortion_swirl_wave dist_swirl_wave;

        switch(m_distortion.cur_item())
        {
            case 0: dist = &dist_wave;       break;
            case 1: dist = &dist_swirl;      break;
            case 2: dist = &dist_wave_swirl; break;
            case 3: dist = &dist_swirl_wave; break;
        }

        dist->period(m_period.value());
        dist->amplitude(m_amplitude.value());
        dist->phase(m_phase);
        double cx = m_center_x;
        double cy = m_center_y;
        img_mtx.transform(&cx, &cy);
        dist->center(cx, cy);

        interpolator_type interpolator(img_mtx, *dist);

        typedef agg::image_accessor_clip<pixfmt> img_source_type;
        img_source_type img_src(img_pixf, agg::rgba(1,1,1));

/*
        // Version without filtering (nearest neighbor)
        //------------------------------------------
        typedef agg::span_image_filter_rgb_nn<img_source_type,
                                              interpolator_type> span_gen_type;
        span_gen_type sg(img_src, interpolator);
        //------------------------------------------
*/

        // Version with "hardcoded" bilinear filter and without 
        // image_accessor (direct filter, the old variant)
        //------------------------------------------
        typedef agg::span_image_filter_rgb_bilinear_clip<pixfmt,
                                                         interpolator_type> span_gen_type;
        span_gen_type sg(img_pixf, agg::rgba(1,1,1), interpolator);
        //------------------------------------------

/*
        // Version with arbitrary 2x2 filter
        //------------------------------------------
        typedef agg::span_image_filter_rgb_2x2<img_source_type,
                                               interpolator_type> span_gen_type;
        agg::image_filter<agg::image_filter_kaiser> filter;
        span_gen_type sg(img_src, interpolator, filter);
        //------------------------------------------
*/
/*
        // Version with arbitrary filter
        //------------------------------------------
        typedef agg::span_image_filter_rgb<img_source_type,
                                           interpolator_type> span_gen_type;
        agg::image_filter<agg::image_filter_spline36> filter;
        span_gen_type sg(img_src, interpolator, filter);
        //------------------------------------------
*/


        agg::rasterizer_scanline_aa<> ras;
        agg::scanline_u8 sl;
        double r = img_width;
        if(img_height < r) r = img_height;
        agg::ellipse ell(img_width  / 2.0, 
                         img_height / 2.0, 
                         r / 2.0 - 20.0, 
                         r / 2.0 - 20.0, 200);


        agg::conv_transform<agg::ellipse> tr(ell, src_mtx);

        ras.add_path(tr);
        agg::render_scanlines_aa(ras, sl, rb, sa, sg);

        src_mtx *= ~trans_affine_resizing();
        src_mtx *= agg::trans_affine_translation(img_width - img_width/10, 0.0);
        src_mtx *= trans_affine_resizing();

        ras.add_path(tr);
        agg::render_scanlines_aa_solid(ras, sl, rb, agg::rgba8(0,0,0));

        typedef agg::span_gradient<agg::rgba8, 
                                   interpolator_type,
                                   agg::gradient_circle,
                                   color_array_type> gradient_span_gen;

        agg::gradient_circle gradient_function;

        color_array_type gradient_colors(m_gradient_colors);
        gradient_span_gen span_gradient(interpolator, 
                                        gradient_function, 
                                        gradient_colors, 
                                        0, 180);

        agg::trans_affine gr1_mtx;
        gr1_mtx *= agg::trans_affine_translation(-img_width/2, -img_height/2);
        gr1_mtx *= agg::trans_affine_scaling(0.8);
        gr1_mtx *= agg::trans_affine_rotation(m_angle.value() * agg::pi / 180.0);
        gr1_mtx *= agg::trans_affine_translation(img_width - img_width/10 + img_width/2 + 10, 
                                                 img_height/2 + 10 + 40);
        gr1_mtx *= trans_affine_resizing();

        agg::trans_affine gr2_mtx;
        gr2_mtx *= agg::trans_affine_rotation(m_angle.value() * agg::pi / 180.0);
        gr2_mtx *= agg::trans_affine_scaling(m_scale.value());
        gr2_mtx *= agg::trans_affine_translation(img_width - img_width/10 + img_width/2 + 10 + 50, 
                                                 img_height/2 + 10 + 40 + 50);
        gr2_mtx *= trans_affine_resizing();
        gr2_mtx.invert();

        cx = m_center_x + img_width - img_width/10;
        cy = m_center_y;
        gr2_mtx.transform(&cx, &cy);
        dist->center(cx, cy);

        interpolator.transformer(gr2_mtx);

        agg::conv_transform<agg::ellipse> tr2(ell, gr1_mtx);

        ras.add_path(tr2);
        agg::render_scanlines_aa(ras, sl, rb, sa, span_gradient);

        agg::render_ctrl(ras, sl, rb, m_angle);
        agg::render_ctrl(ras, sl, rb, m_scale);
        agg::render_ctrl(ras, sl, rb, m_amplitude);
        agg::render_ctrl(ras, sl, rb, m_period);
        agg::render_ctrl(ras, sl, rb, m_distortion);
    }
    void operator() (marker_svg const& marker)
    {
        agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_);
        auto image_transform = get_optional<transform_type>(sym_, keys::image_transform);
        if (image_transform) evaluate_transform(image_tr, feature_, common_.vars_, *image_transform);
        mapnik::box2d<double> const& bbox_image = marker.get_data()->bounding_box() * image_tr;
        mapnik::image_rgba8 image(bbox_image.width(), bbox_image.height());
        render_pattern<buffer_type>(*ras_ptr_, marker, image_tr, 1.0, image);

        agg::rendering_buffer buf(current_buffer_->bytes(), current_buffer_->width(),
                                  current_buffer_->height(), current_buffer_->row_size());
        ras_ptr_->reset();
        value_double gamma = get<value_double, keys::gamma>(sym_, feature_, common_.vars_);
        gamma_method_enum gamma_method = get<gamma_method_enum, keys::gamma_method>(sym_, feature_, common_.vars_);
        if (gamma != gamma_ || gamma_method != gamma_method_)
        {
            set_gamma_method(ras_ptr_, gamma, gamma_method);
            gamma_method_ = gamma_method;
            gamma_ = gamma;
        }

        value_bool clip = get<value_bool, keys::clip>(sym_, feature_, common_.vars_);
        value_double opacity = get<double, keys::opacity>(sym_, feature_, common_.vars_);
        value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym_, feature_, common_.vars_);
        value_double smooth = get<value_double, keys::smooth>(sym_, feature_, common_.vars_);

        box2d<double> clip_box = clipping_extent(common_);

        using color = agg::rgba8;
        using order = agg::order_rgba;
        using blender_type = agg::comp_op_adaptor_rgba_pre<color, order>;
        using pixfmt_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;

        using wrap_x_type = agg::wrap_mode_repeat;
        using wrap_y_type = agg::wrap_mode_repeat;
        using img_source_type = agg::image_accessor_wrap<agg::pixfmt_rgba32_pre,
                                                         wrap_x_type,
                                                         wrap_y_type>;

        using span_gen_type = agg::span_pattern_rgba<img_source_type>;
        using ren_base = agg::renderer_base<pixfmt_type>;

        using renderer_type = agg::renderer_scanline_aa_alpha<ren_base,
                                                              agg::span_allocator<agg::rgba8>,
                                                              span_gen_type>;

        pixfmt_type pixf(buf);
        pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym_, feature_, common_.vars_)));
        ren_base renb(pixf);

        unsigned w = image.width();
        unsigned h = image.height();
        agg::rendering_buffer pattern_rbuf((agg::int8u*)image.bytes(),w,h,w*4);
        agg::pixfmt_rgba32_pre pixf_pattern(pattern_rbuf);
        img_source_type img_src(pixf_pattern);

        pattern_alignment_enum alignment = get<pattern_alignment_enum, keys::alignment>(sym_, feature_, common_.vars_);
        unsigned offset_x=0;
        unsigned offset_y=0;

        if (alignment == LOCAL_ALIGNMENT)
        {
            double x0 = 0;
            double y0 = 0;
            using apply_local_alignment = detail::apply_local_alignment;
            apply_local_alignment apply(common_.t_,prj_trans_, clip_box, x0, y0);
            util::apply_visitor(geometry::vertex_processor<apply_local_alignment>(apply), feature_.get_geometry());
            offset_x = unsigned(current_buffer_->width() - x0);
            offset_y = unsigned(current_buffer_->height() - y0);
        }

        span_gen_type sg(img_src, offset_x, offset_y);

        agg::span_allocator<agg::rgba8> sa;
        renderer_type rp(renb,sa, sg, unsigned(opacity * 255));

        agg::trans_affine tr;
        auto transform = get_optional<transform_type>(sym_, keys::geometry_transform);
        if (transform) evaluate_transform(tr, feature_, common_.vars_, *transform, common_.scale_factor_);
        using vertex_converter_type = vertex_converter<clip_poly_tag,
                                                       transform_tag,
                                                       affine_transform_tag,
                                                       simplify_tag,
                                                       smooth_tag>;

        vertex_converter_type converter(clip_box,sym_,common_.t_,prj_trans_,tr,feature_,common_.vars_,common_.scale_factor_);


        if (prj_trans_.equal() && clip) converter.set<clip_poly_tag>();
        converter.set<transform_tag>(); //always transform
        converter.set<affine_transform_tag>(); // optional affine transform
        if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
        if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter

        using apply_vertex_converter_type = detail::apply_vertex_converter<vertex_converter_type, rasterizer>;
        using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>;
        apply_vertex_converter_type apply(converter, *ras_ptr_);
        mapnik::util::apply_visitor(vertex_processor_type(apply),feature_.get_geometry());
        agg::scanline_u8 sl;
        ras_ptr_->filling_rule(agg::fill_even_odd);
        agg::render_scanlines(*ras_ptr_, sl, rp);
    }
void agg_renderer<T>::process(polygon_pattern_symbolizer const& sym,
                              Feature const& feature,
                              proj_transform const& prj_trans)
{
    typedef coord_transform2<CoordTransform,geometry_type> path_type;
    typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base;
    typedef agg::wrap_mode_repeat wrap_x_type;
    typedef agg::wrap_mode_repeat wrap_y_type;
    typedef agg::pixfmt_alpha_blend_rgba<agg::blender_rgba32_plain,
        agg::row_accessor<agg::int8u>, agg::pixel32_type> rendering_buffer;
    typedef agg::image_accessor_wrap<rendering_buffer,
        wrap_x_type,
        wrap_y_type> img_source_type;

    typedef agg::span_pattern_rgba<img_source_type> span_gen_type;

    typedef agg::renderer_scanline_aa<ren_base,
        agg::span_allocator<agg::rgba8>,
        span_gen_type> renderer_type;


    agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4);
    agg::pixfmt_rgba32_plain pixf(buf);
    ren_base renb(pixf);
    
    agg::scanline_u8 sl;
    ras_ptr->reset();
    switch (sym.get_gamma_method())
    {
        case GAMMA_POWER:
            ras_ptr->gamma(agg::gamma_power(sym.get_gamma()));
            break;
        case GAMMA_LINEAR:
            ras_ptr->gamma(agg::gamma_linear(0.0, sym.get_gamma()));
            break;
        case GAMMA_NONE:
            ras_ptr->gamma(agg::gamma_none());
            break;
        case GAMMA_THRESHOLD:
            ras_ptr->gamma(agg::gamma_threshold(sym.get_gamma()));
            break;
        case GAMMA_MULTIPLY:
            ras_ptr->gamma(agg::gamma_multiply(sym.get_gamma()));
            break;
        default:
            ras_ptr->gamma(agg::gamma_power(sym.get_gamma()));
    }

    std::string filename = path_processor_type::evaluate( *sym.get_filename(), feature);
    boost::optional<mapnik::marker_ptr> marker;
    if ( !filename.empty() )
    {
        marker = marker_cache::instance()->find(filename, true);
    }
    else
    {
        std::clog << "### Warning: file not found: " << filename << "\n";
    }

    if (!marker || !(*marker)->is_bitmap()) return;
    

    boost::optional<image_ptr> pat = (*marker)->get_bitmap_data();

    if (!pat) return;
    
    unsigned w=(*pat)->width();
    unsigned h=(*pat)->height();
    agg::row_accessor<agg::int8u> pattern_rbuf((agg::int8u*)(*pat)->getBytes(),w,h,w*4);
    agg::span_allocator<agg::rgba8> sa;
    agg::pixfmt_alpha_blend_rgba<agg::blender_rgba32_plain,
        agg::row_accessor<agg::int8u>, agg::pixel32_type> pixf_pattern(pattern_rbuf);
    img_source_type img_src(pixf_pattern);
    
    unsigned num_geometries = feature.num_geometries();

    pattern_alignment_e align = sym.get_alignment();
    unsigned offset_x=0;
    unsigned offset_y=0;
    
    if (align == LOCAL_ALIGNMENT)
    {
        double x0=0,y0=0;
        if (num_geometries>0)
        {
            path_type path(t_,feature.get_geometry(0),prj_trans);
            path.vertex(&x0,&y0);
        }
        offset_x = unsigned(width_-x0);
        offset_y = unsigned(height_-y0);    
    }
    
    span_gen_type sg(img_src, offset_x, offset_y);
    renderer_type rp(renb,sa, sg);
    metawriter_with_properties writer = sym.get_metawriter();
    for (unsigned i=0;i<num_geometries;++i)
    {
        geometry_type const& geom = feature.get_geometry(i);
        if (geom.num_points() > 2)
        {
            path_type path(t_,geom,prj_trans);
            ras_ptr->add_path(path);
            if (writer.first) writer.first->add_polygon(path, feature, t_, writer.second);
        }
    }
    agg::render_scanlines(*ras_ptr, sl, rp);
}
Exemple #14
0
void scale_image_agg(Image & target,
                     Image const& source,
                     scaling_method_e scaling_method,
                     double image_ratio,
                     double x_off_f,
                     double y_off_f,
                     double filter_radius,
                     double ratio)
{
    // "the image filters should work namely in the premultiplied color space"
    // http://old.nabble.com/Re:--AGG--Basic-image-transformations-p1110665.html
    // "Yes, you need to use premultiplied images only. Only in this case the simple weighted averaging works correctly in the image fitering."
    // http://permalink.gmane.org/gmane.comp.graphics.agg/3443
    typedef agg::pixfmt_rgba32_pre pixfmt_pre;
    typedef agg::renderer_base<pixfmt_pre> renderer_base_pre;

    // define some stuff we'll use soon
    agg::rasterizer_scanline_aa<> ras;
    agg::scanline_u8 sl;
    agg::span_allocator<agg::rgba8> sa;
    agg::image_filter_lut filter;

    // initialize source AGG buffer
    agg::rendering_buffer rbuf_src((unsigned char*)source.getBytes(), source.width(), source.height(), source.width() * 4);
    pixfmt_pre pixf_src(rbuf_src);
    typedef agg::image_accessor_clone<pixfmt_pre> img_src_type;
    img_src_type img_src(pixf_src);

    // initialize destination AGG buffer (with transparency)
    agg::rendering_buffer rbuf_dst((unsigned char*)target.getBytes(), target.width(), target.height(), target.width() * 4);
    pixfmt_pre pixf_dst(rbuf_dst);
    renderer_base_pre rb_dst_pre(pixf_dst);
    rb_dst_pre.clear(agg::rgba(0, 0, 0, 0));

    // create a scaling matrix
    agg::trans_affine img_mtx;
    img_mtx /= agg::trans_affine_scaling(image_ratio * ratio, image_ratio * ratio);

    // create a linear interpolator for our scaling matrix
    typedef agg::span_interpolator_linear<> interpolator_type;
    interpolator_type interpolator(img_mtx);

    // draw an anticlockwise polygon to render our image into
    double scaled_width = target.width();
    double scaled_height = target.height();
    ras.reset();
    ras.move_to_d(x_off_f,                y_off_f);
    ras.line_to_d(x_off_f + scaled_width, y_off_f);
    ras.line_to_d(x_off_f + scaled_width, y_off_f + scaled_height);
    ras.line_to_d(x_off_f,                y_off_f + scaled_height);

    switch(scaling_method)
    {
    case SCALING_NEAR:
    {
        typedef agg::span_image_filter_rgba_nn<img_src_type, interpolator_type> span_gen_type;
        span_gen_type sg(img_src, interpolator);
        agg::render_scanlines_aa(ras, sl, rb_dst_pre, sa, sg);
        return;
    }
    case SCALING_BILINEAR:
    case SCALING_BILINEAR8:
        filter.calculate(agg::image_filter_bilinear(), true); break;
    case SCALING_BICUBIC:
        filter.calculate(agg::image_filter_bicubic(), true); break;
    case SCALING_SPLINE16:
        filter.calculate(agg::image_filter_spline16(), true); break;
    case SCALING_SPLINE36:
        filter.calculate(agg::image_filter_spline36(), true); break;
    case SCALING_HANNING:
        filter.calculate(agg::image_filter_hanning(), true); break;
    case SCALING_HAMMING:
        filter.calculate(agg::image_filter_hamming(), true); break;
    case SCALING_HERMITE:
        filter.calculate(agg::image_filter_hermite(), true); break;
    case SCALING_KAISER:
        filter.calculate(agg::image_filter_kaiser(), true); break;
    case SCALING_QUADRIC:
        filter.calculate(agg::image_filter_quadric(), true); break;
    case SCALING_CATROM:
        filter.calculate(agg::image_filter_catrom(), true); break;
    case SCALING_GAUSSIAN:
        filter.calculate(agg::image_filter_gaussian(), true); break;
    case SCALING_BESSEL:
        filter.calculate(agg::image_filter_bessel(), true); break;
    case SCALING_MITCHELL:
        filter.calculate(agg::image_filter_mitchell(), true); break;
    case SCALING_SINC:
        filter.calculate(agg::image_filter_sinc(filter_radius), true); break;
    case SCALING_LANCZOS:
        filter.calculate(agg::image_filter_lanczos(filter_radius), true); break;
    case SCALING_BLACKMAN:
        filter.calculate(agg::image_filter_blackman(filter_radius), true); break;
    }
    // details on various resampling considerations
    // http://old.nabble.com/Re%3A-Newbie---texture-p5057255.html

    // high quality resampler
    //typedef agg::span_image_resample_rgba_affine<img_src_type> span_gen_type;

    // faster, lower quality
    //typedef agg::span_image_filter_rgba<img_src_type,interpolator_type> span_gen_type;

    // local, modified agg::span_image_resample_rgba_affine
    // not convinced we need this
    // https://github.com/mapnik/mapnik/issues/1489
    typedef mapnik::span_image_resample_rgba_affine<img_src_type> span_gen_type;
    span_gen_type sg(img_src, interpolator, filter);
    agg::render_scanlines_aa(ras, sl, rb_dst_pre, sa, sg);
}
void agg_renderer<T0,T1>::process(polygon_pattern_symbolizer const& sym,
                                  mapnik::feature_impl & feature,
                                  proj_transform const& prj_trans)
{
    std::string filename = get<std::string, keys::file>(sym, feature, common_.vars_);
    std::shared_ptr<mapnik::marker const> marker = marker_cache::instance().find(filename, true);
    if (marker->is<marker_null>())
    {
        return;
    }

    buffer_type & current_buffer = buffers_.top().get();
    agg::rendering_buffer buf(current_buffer.bytes(), current_buffer.width(),
                              current_buffer.height(), current_buffer.row_size());
    ras_ptr->reset();
    value_double gamma = get<value_double, keys::gamma>(sym, feature, common_.vars_);
    gamma_method_enum gamma_method = get<gamma_method_enum, keys::gamma_method>(sym, feature, common_.vars_);
    if (gamma != gamma_ || gamma_method != gamma_method_)
    {
        set_gamma_method(ras_ptr, gamma, gamma_method);
        gamma_method_ = gamma_method;
        gamma_ = gamma;
    }

    using vertex_converter_type = vertex_converter<transform2_tag,
                                                   clip_poly_tag,
                                                   transform_tag,
                                                   affine_transform_tag,
                                                   simplify_tag,
                                                   smooth_tag>;
    using pattern_type = agg_polygon_pattern<vertex_converter_type>;

    common_pattern_process_visitor visitor(common_, sym, feature);
    image_rgba8 image(util::apply_visitor(visitor, *marker));

    pattern_type pattern(image, common_, sym, feature, prj_trans);

    pattern_type::pixfmt_type pixf(buf);
    pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e, keys::comp_op>(sym, feature, common_.vars_)));
    pattern_type::renderer_base renb(pixf);

    unsigned w = image.width();
    unsigned h = image.height();
    agg::rendering_buffer pattern_rbuf((agg::int8u*)image.bytes(),w,h,w*4);
    agg::pixfmt_rgba32_pre pixf_pattern(pattern_rbuf);
    pattern_type::img_source_type img_src(pixf_pattern);

    if (pattern.clip_ && !pattern.prj_trans_.equal())
    {
        pattern.converter_.template set<transform2_tag>();
    }
    else
    {
        pattern.converter_.template set<transform_tag>();
    }

    if (pattern.clip_) pattern.converter_.set<clip_poly_tag>();

    ras_ptr->filling_rule(agg::fill_even_odd);

    pattern.render(renb, *ras_ptr);
}