agg/examples/pattern_resample.cpp

400 lines
13 KiB
C++
Raw Permalink Normal View History

2021-12-27 20:14:31 +01:00
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#include "agg_rendering_buffer.h"
#include "agg_rasterizer_scanline_aa.h"
#include "agg_scanline_u.h"
#include "agg_renderer_scanline.h"
#include "agg_path_storage.h"
#include "agg_conv_transform.h"
#include "agg_trans_affine.h"
#include "agg_span_allocator.h"
#include "agg_span_interpolator_linear.h"
#include "agg_span_interpolator_trans.h"
#include "agg_span_interpolator_persp.h"
#include "agg_span_subdiv_adaptor.h"
#include "agg_image_accessors.h"
#include "agg_gamma_lut.h"
#include "ctrl/agg_rbox_ctrl.h"
#include "ctrl/agg_slider_ctrl.h"
#include "platform/agg_platform_support.h"
#include "interactive_polygon.h"
int global_offset = 0;
enum flip_y_e { flip_y = true };
agg::rasterizer_scanline_aa<> g_rasterizer;
agg::scanline_u8 g_scanline;
double g_x1 = 0;
double g_y1 = 0;
double g_x2 = 0;
double g_y2 = 0;
#include "agg_pixfmt_rgb.h"
#include "agg_span_image_filter_rgb.h"
#define pix_format agg::pix_format_bgr24
typedef agg::pixfmt_bgr24 pixfmt;
typedef agg::pixfmt_bgr24_pre pixfmt_pre;
#define span_image_filter_2x2 agg::span_image_filter_rgb_2x2
#define span_image_resample_affine agg::span_image_resample_rgb_affine
#define span_image_resample agg::span_image_resample_rgb
typedef pixfmt::color_type color_type;
typedef color_type::value_type value_type;
typedef agg::renderer_base<pixfmt> renderer_base;
typedef agg::renderer_base<pixfmt_pre> renderer_base_pre;
typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_solid;
enum base_scale_e { base_shift = color_type::base_shift };
class the_application : public agg::platform_support
{
public:
agg::gamma_lut<value_type, value_type, base_shift, base_shift> m_gamma_lut;
agg::interactive_polygon m_quad;
agg::rbox_ctrl<agg::rgba> m_trans_type;
agg::slider_ctrl<agg::rgba> m_gamma;
agg::slider_ctrl<agg::rgba> m_blur;
double m_old_gamma;
the_application(agg::pix_format_e format, bool flip_y) :
agg::platform_support(format, flip_y),
m_gamma_lut(2.0),
m_quad(4, 5.0),
m_trans_type(400, 5.0, 430+170.0, 100.0, !flip_y),
m_gamma(5.0, 5.0+15*0, 400-5, 10.0+15*0, !flip_y),
m_blur (5.0, 5.0+15*1, 400-5, 10.0+15*1, !flip_y),
m_old_gamma(2.0)
{
m_trans_type.text_size(7);
m_trans_type.add_item("Affine No Resample");
m_trans_type.add_item("Affine Resample");
m_trans_type.add_item("Perspective No Resample LERP");
m_trans_type.add_item("Perspective No Resample Exact");
m_trans_type.add_item("Perspective Resample LERP");
m_trans_type.add_item("Perspective Resample Exact");
m_trans_type.cur_item(4);
add_ctrl(m_trans_type);
m_gamma.range(0.5, 3.0);
m_gamma.value(2.0);
m_gamma.label("Gamma=%.3f");
add_ctrl(m_gamma);
m_blur.range(0.5, 2.0);
m_blur.value(1.0);
m_blur.label("Blur=%.3f");
add_ctrl(m_blur);
}
virtual void on_init()
{
g_x1 = -150;
g_y1 = -150;
g_x2 = 150;
g_y2 = 150;
double trans_x1 = -200;
double trans_y1 = -200;
double trans_x2 = 200;
double trans_y2 = 200;
double dx = width() / 2.0 - (trans_x2 + trans_x1) / 2.0;
double dy = height() / 2.0 - (trans_y2 + trans_y1) / 2.0;
m_quad.xn(0) = floor(trans_x1 + dx);
m_quad.yn(0) = floor(trans_y1 + dy);
m_quad.xn(1) = floor(trans_x2 + dx);
m_quad.yn(1) = floor(trans_y1 + dy);
m_quad.xn(2) = floor(trans_x2 + dx);
m_quad.yn(2) = floor(trans_y2 + dy);
m_quad.xn(3) = floor(trans_x1 + dx);
m_quad.yn(3) = floor(trans_y2 + dy);
pixfmt pixf(rbuf_img(0));
pixf.apply_gamma_dir(m_gamma_lut);
}
virtual void on_draw()
{
if(m_gamma.value() != m_old_gamma)
{
m_gamma_lut.gamma(m_gamma.value());
load_img(0, "agg");
pixfmt pixf(rbuf_img(0));
pixf.apply_gamma_dir(m_gamma_lut);
m_old_gamma = m_gamma.value();
}
pixfmt pixf(rbuf_window());
pixfmt_pre pixf_pre(rbuf_window());
renderer_base rb(pixf);
renderer_base_pre rb_pre(pixf_pre);
renderer_solid r(rb);
rb.clear(agg::rgba(1, 1, 1));
if(m_trans_type.cur_item() < 2)
{
// 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));
}
//--------------------------
// Render the "quad" tool and controls
g_rasterizer.add_path(m_quad);
r.color(agg::rgba(0, 0.3, 0.5, 0.1));
agg::render_scanlines(g_rasterizer, g_scanline, r);
// 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();
int b = 0;
g_rasterizer.move_to_d(m_quad.xn(0)-b, m_quad.yn(0)-b);
g_rasterizer.line_to_d(m_quad.xn(1)+b, m_quad.yn(1)-b);
g_rasterizer.line_to_d(m_quad.xn(2)+b, m_quad.yn(2)+b);
g_rasterizer.line_to_d(m_quad.xn(3)-b, m_quad.yn(3)+b);
typedef agg::span_allocator<color_type> span_alloc_type;
span_alloc_type sa;
agg::image_filter_hanning filter_kernel;
agg::image_filter_lut filter(filter_kernel, true);
typedef agg::wrap_mode_reflect_auto_pow2 wrap_type;
typedef agg::image_accessor_wrap<pixfmt, wrap_type, wrap_type> img_source_type;
pixfmt img_pixf(rbuf_img(0));
img_source_type img_src(img_pixf);
start_timer();
switch(m_trans_type.cur_item())
{
case 0:
{
agg::trans_affine tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2);
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_affine tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2);
typedef agg::span_interpolator_linear<agg::trans_affine> interpolator_type;
typedef span_image_resample_affine<img_source_type> span_gen_type;
interpolator_type interpolator(tr);
span_gen_type sg(img_src, interpolator, filter);
sg.blur(m_blur.value());
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> 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 3:
{
agg::trans_perspective tr(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2);
if(tr.is_valid())
{
typedef agg::span_interpolator_trans<agg::trans_perspective> 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 4:
{
typedef agg::span_interpolator_persp_lerp<> interpolator_type;
typedef agg::span_subdiv_adaptor<interpolator_type> subdiv_adaptor_type;
interpolator_type interpolator(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2);
subdiv_adaptor_type subdiv_adaptor(interpolator);
if(interpolator.is_valid())
{
typedef span_image_resample<img_source_type,
subdiv_adaptor_type> span_gen_type;
span_gen_type sg(img_src, subdiv_adaptor, filter);
sg.blur(m_blur.value());
agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg);
}
break;
}
case 5:
{
typedef agg::span_interpolator_persp_exact<> interpolator_type;
typedef agg::span_subdiv_adaptor<interpolator_type> subdiv_adaptor_type;
interpolator_type interpolator(m_quad.polygon(), g_x1, g_y1, g_x2, g_y2);
subdiv_adaptor_type subdiv_adaptor(interpolator);
if(interpolator.is_valid())
{
typedef span_image_resample<img_source_type,
subdiv_adaptor_type> span_gen_type;
span_gen_type sg(img_src, subdiv_adaptor, filter);
sg.blur(m_blur.value());
agg::render_scanlines_aa(g_rasterizer, g_scanline, rb_pre, sa, sg);
}
break;
}
}
double tm = elapsed_time();
pixf.apply_gamma_inv(m_gamma_lut);
char buf[64];
agg::gsv_text t;
t.size(10.0);
agg::conv_stroke<agg::gsv_text> pt(t);
pt.width(1.5);
sprintf(buf, "%3.2f ms", tm);
t.start_point(10.0, 70.0);
t.text(buf);
g_rasterizer.add_path(pt);
r.color(agg::rgba(0,0,0));
agg::render_scanlines(g_rasterizer, g_scanline, r);
//--------------------------
agg::render_ctrl(g_rasterizer, g_scanline, rb, m_trans_type);
agg::render_ctrl(g_rasterizer, g_scanline, rb, m_gamma);
agg::render_ctrl(g_rasterizer, g_scanline, rb, m_blur);
}
virtual void on_mouse_button_down(int x, int y, unsigned flags)
{
if(flags & agg::mouse_left)
{
if(m_quad.on_mouse_button_down(x, y))
{
force_redraw();
}
}
}
virtual void on_mouse_move(int x, int y, unsigned flags)
{
if(flags & agg::mouse_left)
{
if(m_quad.on_mouse_move(x, y))
{
force_redraw();
}
}
if((flags & agg::mouse_left) == 0)
{
on_mouse_button_up(x, y, flags);
}
}
virtual void on_mouse_button_up(int x, int y, unsigned flags)
{
if(m_quad.on_mouse_button_up(x, y))
{
force_redraw();
}
}
virtual void on_key(int x, int y, unsigned key, unsigned flags)
{
if(key == ' ')
{
double cx = (m_quad.xn(0) + m_quad.xn(1) + m_quad.xn(2) + m_quad.xn(3)) / 4;
double cy = (m_quad.yn(0) + m_quad.yn(1) + m_quad.yn(2) + m_quad.yn(3)) / 4;
agg::trans_affine tr = agg::trans_affine_translation(-cx, -cy);
tr *= agg::trans_affine_rotation(agg::pi / 2.0);
tr *= agg::trans_affine_translation(cx, cy);
tr.transform(&m_quad.xn(0), &m_quad.yn(0));
tr.transform(&m_quad.xn(1), &m_quad.yn(1));
tr.transform(&m_quad.xn(2), &m_quad.yn(2));
tr.transform(&m_quad.xn(3), &m_quad.yn(3));
force_redraw();
}
}
};
int agg_main(int argc, char* argv[])
{
the_application app(pix_format, flip_y);
app.caption("AGG Example. Pattern Transformations with Resampling");
const char* img_name = "agg";
if(argc >= 2) img_name = argv[1];
if(!app.load_img(0, img_name))
{
char buf[256];
if(strcmp(img_name, "agg") == 0)
{
sprintf(buf, "File not found: %s%s. Download http://www.antigrain.com/%s%s\n"
"or copy it from the ../art directory.",
img_name, app.img_ext(), img_name, app.img_ext());
}
else
{
sprintf(buf, "File not found: %s%s", img_name, app.img_ext());
}
app.message(buf);
return 1;
}
if(app.init(600, 600, agg::window_resize))
{
return app.run();
}
return 1;
}