Example #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;
}
Example #2
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);
    }

}
Example #3
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);
}