316 lines
11 KiB
C++
316 lines
11 KiB
C++
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
#include "agg_rendering_buffer.h"
|
|
#include "agg_rasterizer_scanline_aa.h"
|
|
#include "agg_ellipse.h"
|
|
#include "agg_trans_affine.h"
|
|
#include "agg_conv_transform.h"
|
|
#include "agg_conv_stroke.h"
|
|
#include "agg_scanline_p.h"
|
|
#include "agg_renderer_scanline.h"
|
|
#include "agg_image_filters.h"
|
|
#include "ctrl/agg_slider_ctrl.h"
|
|
#include "ctrl/agg_rbox_ctrl.h"
|
|
#include "ctrl/agg_cbox_ctrl.h"
|
|
#include "platform/agg_platform_support.h"
|
|
|
|
#define AGG_BGR24
|
|
//#define AGG_BGR96
|
|
#include "pixel_formats.h"
|
|
|
|
enum flip_y_e { flip_y = true };
|
|
|
|
|
|
struct filter_base
|
|
{
|
|
virtual double radius() const = 0;
|
|
virtual void set_radius(double r) = 0;
|
|
virtual double calc_weight(double x) const = 0;
|
|
};
|
|
|
|
|
|
template<class Filter> struct image_filter_const_radius_adaptor : filter_base
|
|
{
|
|
virtual double radius() const { return m_filter.radius(); }
|
|
virtual void set_radius(double r) {}
|
|
virtual double calc_weight(double x) const { return m_filter.calc_weight(fabs(x)); }
|
|
Filter m_filter;
|
|
};
|
|
|
|
|
|
template<class Filter> struct image_filter_variable_radius_adaptor : filter_base
|
|
{
|
|
virtual double radius() const { return m_filter.radius(); }
|
|
virtual double calc_weight(double x) const { return m_filter.calc_weight(fabs(x)); }
|
|
virtual void set_radius(double r) { m_filter = Filter(r); }
|
|
image_filter_variable_radius_adaptor() : m_filter(2.0) {}
|
|
Filter m_filter;
|
|
};
|
|
|
|
|
|
|
|
class the_application : public agg::platform_support
|
|
{
|
|
agg::slider_ctrl<agg::rgba> m_radius;
|
|
agg::cbox_ctrl<agg::rgba> m_bilinear;
|
|
agg::cbox_ctrl<agg::rgba> m_bicubic;
|
|
agg::cbox_ctrl<agg::rgba> m_spline16;
|
|
agg::cbox_ctrl<agg::rgba> m_spline36;
|
|
agg::cbox_ctrl<agg::rgba> m_hanning;
|
|
agg::cbox_ctrl<agg::rgba> m_hamming;
|
|
agg::cbox_ctrl<agg::rgba> m_hermite;
|
|
agg::cbox_ctrl<agg::rgba> m_kaiser;
|
|
agg::cbox_ctrl<agg::rgba> m_quadric;
|
|
agg::cbox_ctrl<agg::rgba> m_catrom;
|
|
agg::cbox_ctrl<agg::rgba> m_gaussian;
|
|
agg::cbox_ctrl<agg::rgba> m_bessel;
|
|
agg::cbox_ctrl<agg::rgba> m_mitchell;
|
|
agg::cbox_ctrl<agg::rgba> m_sinc;
|
|
agg::cbox_ctrl<agg::rgba> m_lanczos;
|
|
agg::cbox_ctrl<agg::rgba> m_blackman;
|
|
agg::cbox_ctrl<agg::rgba>* m_filters[32];
|
|
|
|
image_filter_const_radius_adaptor<agg::image_filter_bilinear> m_filter_bilinear;
|
|
image_filter_const_radius_adaptor<agg::image_filter_bicubic> m_filter_bicubic;
|
|
image_filter_const_radius_adaptor<agg::image_filter_spline16> m_filter_spline16;
|
|
image_filter_const_radius_adaptor<agg::image_filter_spline36> m_filter_spline36;
|
|
image_filter_const_radius_adaptor<agg::image_filter_hanning> m_filter_hanning;
|
|
image_filter_const_radius_adaptor<agg::image_filter_hamming> m_filter_hamming;
|
|
image_filter_const_radius_adaptor<agg::image_filter_hermite> m_filter_hermite;
|
|
image_filter_const_radius_adaptor<agg::image_filter_kaiser> m_filter_kaiser;
|
|
image_filter_const_radius_adaptor<agg::image_filter_quadric> m_filter_quadric;
|
|
image_filter_const_radius_adaptor<agg::image_filter_catrom> m_filter_catrom;
|
|
image_filter_const_radius_adaptor<agg::image_filter_gaussian> m_filter_gaussian;
|
|
image_filter_const_radius_adaptor<agg::image_filter_bessel> m_filter_bessel;
|
|
image_filter_const_radius_adaptor<agg::image_filter_mitchell> m_filter_mitchell;
|
|
image_filter_variable_radius_adaptor<agg::image_filter_sinc> m_filter_sinc;
|
|
image_filter_variable_radius_adaptor<agg::image_filter_lanczos> m_filter_lanczos;
|
|
image_filter_variable_radius_adaptor<agg::image_filter_blackman> m_filter_blackman;
|
|
|
|
filter_base* m_filter_func[32];
|
|
unsigned m_num_filters;
|
|
|
|
|
|
public:
|
|
the_application(agg::pix_format_e format, bool flip_y) :
|
|
agg::platform_support(format, flip_y),
|
|
m_radius (5.0, 5.0, 780-5, 10.0, !flip_y),
|
|
m_bilinear (8.0, 30.0+15*0, "bilinear", !flip_y),
|
|
m_bicubic (8.0, 30.0+15*1, "bicubic ", !flip_y),
|
|
m_spline16 (8.0, 30.0+15*2, "spline16", !flip_y),
|
|
m_spline36 (8.0, 30.0+15*3, "spline36", !flip_y),
|
|
m_hanning (8.0, 30.0+15*4, "hanning ", !flip_y),
|
|
m_hamming (8.0, 30.0+15*5, "hamming ", !flip_y),
|
|
m_hermite (8.0, 30.0+15*6, "hermite ", !flip_y),
|
|
m_kaiser (8.0, 30.0+15*7, "kaiser ", !flip_y),
|
|
m_quadric (8.0, 30.0+15*8, "quadric ", !flip_y),
|
|
m_catrom (8.0, 30.0+15*9, "catrom ", !flip_y),
|
|
m_gaussian (8.0, 30.0+15*10, "gaussian", !flip_y),
|
|
m_bessel (8.0, 30.0+15*11, "bessel ", !flip_y),
|
|
m_mitchell (8.0, 30.0+15*12, "mitchell", !flip_y),
|
|
m_sinc (8.0, 30.0+15*13, "sinc ", !flip_y),
|
|
m_lanczos (8.0, 30.0+15*14, "lanczos ", !flip_y),
|
|
m_blackman (8.0, 30.0+15*15, "blackman", !flip_y),
|
|
m_num_filters(0)
|
|
{
|
|
m_filters[m_num_filters++] = &m_bilinear;
|
|
m_filters[m_num_filters++] = &m_bicubic;
|
|
m_filters[m_num_filters++] = &m_spline16;
|
|
m_filters[m_num_filters++] = &m_spline36;
|
|
m_filters[m_num_filters++] = &m_hanning;
|
|
m_filters[m_num_filters++] = &m_hamming;
|
|
m_filters[m_num_filters++] = &m_hermite;
|
|
m_filters[m_num_filters++] = &m_kaiser;
|
|
m_filters[m_num_filters++] = &m_quadric;
|
|
m_filters[m_num_filters++] = &m_catrom;
|
|
m_filters[m_num_filters++] = &m_gaussian;
|
|
m_filters[m_num_filters++] = &m_bessel;
|
|
m_filters[m_num_filters++] = &m_mitchell;
|
|
m_filters[m_num_filters++] = &m_sinc;
|
|
m_filters[m_num_filters++] = &m_lanczos;
|
|
m_filters[m_num_filters++] = &m_blackman;
|
|
|
|
unsigned i = 0;
|
|
|
|
m_filter_func[i++] = &m_filter_bilinear;
|
|
m_filter_func[i++] = &m_filter_bicubic;
|
|
m_filter_func[i++] = &m_filter_spline16;
|
|
m_filter_func[i++] = &m_filter_spline36;
|
|
m_filter_func[i++] = &m_filter_hanning;
|
|
m_filter_func[i++] = &m_filter_hamming;
|
|
m_filter_func[i++] = &m_filter_hermite;
|
|
m_filter_func[i++] = &m_filter_kaiser;
|
|
m_filter_func[i++] = &m_filter_quadric;
|
|
m_filter_func[i++] = &m_filter_catrom;
|
|
m_filter_func[i++] = &m_filter_gaussian;
|
|
m_filter_func[i++] = &m_filter_bessel;
|
|
m_filter_func[i++] = &m_filter_mitchell;
|
|
m_filter_func[i++] = &m_filter_sinc;
|
|
m_filter_func[i++] = &m_filter_lanczos;
|
|
m_filter_func[i++] = &m_filter_blackman;
|
|
for(i = 0; i < m_num_filters; i++)
|
|
{
|
|
add_ctrl(*m_filters[i]);
|
|
}
|
|
|
|
m_radius.range(2.0, 8.0);
|
|
m_radius.value(4.0);
|
|
m_radius.label("Radius=%.3f");
|
|
add_ctrl(m_radius);
|
|
}
|
|
|
|
virtual ~the_application()
|
|
{
|
|
}
|
|
|
|
virtual void on_draw()
|
|
{
|
|
typedef agg::renderer_base<pixfmt> renderer_base;
|
|
typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_solid;
|
|
|
|
pixfmt pixf(rbuf_window());
|
|
renderer_base rb(pixf);
|
|
renderer_solid rs(rb);
|
|
|
|
rb.clear(agg::rgba(1.0, 1.0, 1.0));
|
|
agg::rasterizer_scanline_aa<> ras;
|
|
agg::scanline_p8 sl;
|
|
|
|
double x_start = 125.0;
|
|
double x_end = initial_width() - 15.0;
|
|
double y_start = 10.0;
|
|
double y_end = initial_height() - 10.0;
|
|
double x_center = (x_start + x_end) / 2;
|
|
|
|
unsigned i;
|
|
|
|
agg::path_storage p;
|
|
agg::conv_stroke<agg::path_storage> pl(p);
|
|
agg::conv_transform<agg::conv_stroke<agg::path_storage> > tr(pl, trans_affine_resizing());
|
|
|
|
for(i = 0; i <= 16; i++)
|
|
{
|
|
double x = x_start + (x_end - x_start) * i / 16.0;
|
|
p.remove_all();
|
|
p.move_to(x+0.5, y_start);
|
|
p.line_to(x+0.5, y_end);
|
|
ras.add_path(tr);
|
|
rs.color(agg::srgba8(0, 0, 0, i == 8 ? 255 : 100));
|
|
agg::render_scanlines(ras, sl, rs);
|
|
}
|
|
|
|
double ys = y_start + (y_end - y_start) / 6.0;
|
|
|
|
p.remove_all();
|
|
p.move_to(x_start, ys);
|
|
p.line_to(x_end, ys);
|
|
ras.add_path(tr);
|
|
rs.color(agg::srgba8(0, 0, 0));
|
|
agg::render_scanlines(ras, sl, rs);
|
|
|
|
|
|
pl.width(1.5);
|
|
|
|
for(i = 0; i < m_num_filters; i++)
|
|
{
|
|
if(m_filters[i]->status())
|
|
{
|
|
m_filter_func[i]->set_radius(m_radius.value());
|
|
unsigned j;
|
|
|
|
double radius = m_filter_func[i]->radius();
|
|
unsigned n = unsigned(radius * 256 * 2);
|
|
double dy = y_end - ys;
|
|
|
|
double xs = (x_end + x_start)/2.0 - (radius * (x_end - x_start) / 16.0);
|
|
double dx = (x_end - x_start) * radius / 8.0;
|
|
|
|
p.remove_all();
|
|
p.move_to(xs+0.5, ys + dy * m_filter_func[i]->calc_weight(-radius));
|
|
for(j = 1; j < n; j++)
|
|
{
|
|
p.line_to(xs + dx * j / n + 0.5,
|
|
ys + dy * m_filter_func[i]->calc_weight(j / 256.0 - radius));
|
|
}
|
|
ras.add_path(tr);
|
|
rs.color(agg::rgba(0.5, 0, 0));
|
|
agg::render_scanlines(ras, sl, rs);
|
|
|
|
p.remove_all();
|
|
unsigned xint;
|
|
int ir = int(ceil(radius) + 0.1);
|
|
|
|
for(xint = 0; xint < 256; xint++)
|
|
{
|
|
int xfract;
|
|
double sum = 0;
|
|
for(xfract = -ir; xfract < ir; xfract++)
|
|
{
|
|
double xf = xint/256.0 + xfract;
|
|
if(xf >= -radius || xf <= radius)
|
|
{
|
|
sum += m_filter_func[i]->calc_weight(xf);
|
|
}
|
|
}
|
|
|
|
double x = x_center + ((-128.0 + xint) / 128.0) * radius * (x_end - x_start) / 16.0;
|
|
double y = ys + sum * 256 - 256;
|
|
|
|
if(xint == 0) p.move_to(x, y);
|
|
else p.line_to(x, y);
|
|
}
|
|
ras.add_path(tr);
|
|
rs.color(agg::rgba(0, 0.5, 0));
|
|
agg::render_scanlines(ras, sl, rs);
|
|
|
|
agg::image_filter_lut normalized(*m_filter_func[i]);
|
|
const agg::int16* weights = normalized.weight_array();
|
|
|
|
xs = (x_end + x_start)/2.0 - (normalized.diameter() * (x_end - x_start) / 32.0);
|
|
unsigned nn = normalized.diameter() * 256;
|
|
p.remove_all();
|
|
p.move_to(xs+0.5, ys + dy * weights[0] / agg::image_filter_scale);
|
|
for(j = 1; j < nn; j++)
|
|
{
|
|
p.line_to(xs + dx * j / n + 0.5,
|
|
ys + dy * weights[j] / agg::image_filter_scale);
|
|
}
|
|
ras.add_path(tr);
|
|
rs.color(agg::rgba(0, 0, 0.5));
|
|
agg::render_scanlines(ras, sl, rs);
|
|
}
|
|
}
|
|
|
|
for(i = 0; i < m_num_filters; i++)
|
|
{
|
|
agg::render_ctrl(ras, sl, rb, *m_filters[i]);
|
|
}
|
|
if(m_sinc.status() || m_lanczos.status() || m_blackman.status())
|
|
{
|
|
agg::render_ctrl(ras, sl, rb, m_radius);
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int agg_main(int argc, char* argv[])
|
|
{
|
|
the_application app(pix_format, flip_y);
|
|
app.caption("Image filters' shape comparison");
|
|
|
|
if(app.init(780, 300, agg::window_resize))
|
|
{
|
|
return app.run();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|