455 lines
13 KiB
C++
455 lines
13 KiB
C++
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <math.h>
|
|
#include "agg_rendering_buffer.h"
|
|
#include "agg_rasterizer_scanline_aa.h"
|
|
#include "agg_path_storage.h"
|
|
#include "agg_trans_affine.h"
|
|
#include "agg_conv_transform.h"
|
|
#include "agg_pixfmt_rgba.h"
|
|
#include "agg_span_image_filter_rgba.h"
|
|
#include "agg_span_interpolator_linear.h"
|
|
#include "agg_scanline_u.h"
|
|
#include "agg_renderer_scanline.h"
|
|
#include "agg_span_allocator.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_BGRA32
|
|
//#define AGG_BGRA128
|
|
#include "pixel_formats.h"
|
|
|
|
enum flip_y_e { flip_y = true };
|
|
|
|
|
|
|
|
|
|
class the_application : public agg::platform_support
|
|
{
|
|
agg::slider_ctrl<agg::rgba> m_polygon_angle;
|
|
agg::slider_ctrl<agg::rgba> m_polygon_scale;
|
|
|
|
agg::slider_ctrl<agg::rgba> m_image_angle;
|
|
agg::slider_ctrl<agg::rgba> m_image_scale;
|
|
|
|
agg::cbox_ctrl<agg::rgba> m_rotate_polygon;
|
|
agg::cbox_ctrl<agg::rgba> m_rotate_image;
|
|
|
|
agg::rbox_ctrl<agg::rgba> m_example;
|
|
|
|
double m_image_center_x;
|
|
double m_image_center_y;
|
|
|
|
double m_polygon_cx;
|
|
double m_polygon_cy;
|
|
|
|
double m_image_cx;
|
|
double m_image_cy;
|
|
|
|
double m_dx;
|
|
double m_dy;
|
|
|
|
int m_flag;
|
|
|
|
|
|
public:
|
|
//------------------------------------------------------------------------
|
|
the_application(agg::pix_format_e format, bool flip_y) :
|
|
agg::platform_support(format, flip_y),
|
|
m_polygon_angle(5, 5, 145, 11, !flip_y),
|
|
m_polygon_scale(5, 5+14, 145, 12+14, !flip_y),
|
|
m_image_angle (155, 5, 300, 12, !flip_y),
|
|
m_image_scale (155, 5+14, 300, 12+14, !flip_y),
|
|
m_rotate_polygon(5, 5+14+14, "Rotate Polygon", !flip_y),
|
|
m_rotate_image (5, 5+14+14+14, "Rotate Image", !flip_y),
|
|
m_example(-3.0, 14+14+14+14, -3.0, 14+14+14+14, !flip_y),
|
|
m_flag(0)
|
|
{
|
|
add_ctrl(m_polygon_angle);
|
|
add_ctrl(m_polygon_scale);
|
|
add_ctrl(m_image_angle);
|
|
add_ctrl(m_image_scale);
|
|
add_ctrl(m_rotate_polygon);
|
|
add_ctrl(m_rotate_image);
|
|
add_ctrl(m_example);
|
|
|
|
m_polygon_angle.label("Polygon Angle=%3.2f");
|
|
m_polygon_scale.label("Polygon Scale=%3.2f");
|
|
m_polygon_angle.range(-180.0, 180.0);
|
|
m_polygon_scale.range(0.1, 5.0);
|
|
m_polygon_scale.value(1.0);
|
|
|
|
m_image_angle.label("Image Angle=%3.2f");
|
|
m_image_scale.label("Image Scale=%3.2f");
|
|
m_image_angle.range(-180.0, 180.0);
|
|
m_image_scale.range(0.1, 5.0);
|
|
m_image_scale.value(1.0);
|
|
|
|
m_example.add_item("0");
|
|
m_example.add_item("1");
|
|
m_example.add_item("2");
|
|
m_example.add_item("3");
|
|
m_example.add_item("4");
|
|
m_example.add_item("5");
|
|
m_example.add_item("6");
|
|
m_example.cur_item(0);
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
virtual ~the_application()
|
|
{
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
virtual void on_init()
|
|
{
|
|
m_image_center_x = initial_width() / 2.0;
|
|
m_image_center_y = initial_height() / 2.0;
|
|
m_polygon_cx = m_image_cx = initial_width() / 2.0;
|
|
m_polygon_cy = m_image_cy = initial_height() / 2.0;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
void create_star(agg::path_storage& ps)
|
|
{
|
|
double r = initial_width();
|
|
if(initial_height() < r) r = initial_height();
|
|
|
|
double r1 = r / 3 - 8.0;
|
|
double r2 = r1 / 1.45;
|
|
unsigned nr = 14;
|
|
|
|
unsigned i;
|
|
for(i = 0; i < nr; i++)
|
|
{
|
|
double a = agg::pi * 2.0 * i / nr - agg::pi / 2.0;
|
|
double dx = cos(a);
|
|
double dy = sin(a);
|
|
|
|
if(i & 1)
|
|
{
|
|
ps.line_to(m_polygon_cx + dx * r1, m_polygon_cy + dy * r1);
|
|
}
|
|
else
|
|
{
|
|
if(i) ps.line_to(m_polygon_cx + dx * r2, m_polygon_cy + dy * r2);
|
|
else ps.move_to(m_polygon_cx + dx * r2, m_polygon_cy + dy * r2);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
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());
|
|
pixfmt pixf_img(rbuf_img(0));
|
|
renderer_base rb(pixf);
|
|
renderer_solid rs(rb);
|
|
|
|
rb.clear(agg::rgba(1.0, 1.0, 1.0));
|
|
|
|
agg::trans_affine image_mtx;
|
|
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);
|
|
|
|
|
|
|
|
switch(m_example.cur_item())
|
|
{
|
|
default:
|
|
case 0:
|
|
// --------------(Example 0, Identity matrix)
|
|
break;
|
|
|
|
|
|
case 1:
|
|
// --------------(Example 1)
|
|
image_mtx *= agg::trans_affine_translation(-m_image_center_x, -m_image_center_y);
|
|
image_mtx *= agg::trans_affine_rotation(m_polygon_angle.value() * agg::pi / 180.0);
|
|
image_mtx *= agg::trans_affine_scaling(m_polygon_scale.value());
|
|
image_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy);
|
|
image_mtx.invert();
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
// --------------(Example 2)
|
|
image_mtx *= agg::trans_affine_translation(-m_image_center_x, -m_image_center_y);
|
|
image_mtx *= agg::trans_affine_rotation(m_image_angle.value() * agg::pi / 180.0);
|
|
image_mtx *= agg::trans_affine_scaling(m_image_scale.value());
|
|
image_mtx *= agg::trans_affine_translation(m_image_cx, m_image_cy);
|
|
image_mtx.invert();
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
// --------------(Example 3)
|
|
image_mtx *= agg::trans_affine_translation(-m_image_center_x, -m_image_center_y);
|
|
image_mtx *= agg::trans_affine_rotation(m_image_angle.value() * agg::pi / 180.0);
|
|
image_mtx *= agg::trans_affine_scaling(m_image_scale.value());
|
|
image_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy);
|
|
image_mtx.invert();
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
// --------------(Example 4)
|
|
image_mtx *= agg::trans_affine_translation(-m_image_cx, -m_image_cy);
|
|
image_mtx *= agg::trans_affine_rotation(m_polygon_angle.value() * agg::pi / 180.0);
|
|
image_mtx *= agg::trans_affine_scaling(m_polygon_scale.value());
|
|
image_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy);
|
|
image_mtx.invert();
|
|
break;
|
|
|
|
|
|
|
|
case 5:
|
|
// --------------(Example 5)
|
|
image_mtx *= agg::trans_affine_translation(-m_image_center_x, -m_image_center_y);
|
|
image_mtx *= agg::trans_affine_rotation(m_image_angle.value() * agg::pi / 180.0);
|
|
image_mtx *= agg::trans_affine_rotation(m_polygon_angle.value() * agg::pi / 180.0);
|
|
image_mtx *= agg::trans_affine_scaling(m_image_scale.value());
|
|
image_mtx *= agg::trans_affine_scaling(m_polygon_scale.value());
|
|
image_mtx *= agg::trans_affine_translation(m_image_cx, m_image_cy);
|
|
image_mtx.invert();
|
|
break;
|
|
|
|
|
|
|
|
case 6:
|
|
// --------------(Example 6)
|
|
image_mtx *= agg::trans_affine_translation(-m_image_cx, -m_image_cy);
|
|
image_mtx *= agg::trans_affine_rotation(m_image_angle.value() * agg::pi / 180.0);
|
|
image_mtx *= agg::trans_affine_scaling(m_image_scale.value());
|
|
image_mtx *= agg::trans_affine_translation(m_image_cx, m_image_cy);
|
|
image_mtx.invert();
|
|
break;
|
|
|
|
}
|
|
|
|
typedef agg::span_interpolator_linear<> interpolator_type;
|
|
interpolator_type interpolator(image_mtx);
|
|
agg::span_allocator<color_type> sa;
|
|
|
|
// "hardcoded" bilinear filter
|
|
//------------------------------------------
|
|
typedef agg::span_image_filter_rgba_bilinear_clip<pixfmt,
|
|
interpolator_type> span_gen_type;
|
|
span_gen_type sg(pixf_img, agg::rgba(1,1,1), interpolator);
|
|
//------------------------------------------
|
|
|
|
agg::rasterizer_scanline_aa<> ras;
|
|
agg::scanline_u8 sl;
|
|
agg::path_storage ps;
|
|
create_star(ps);
|
|
|
|
agg::conv_transform<agg::path_storage> tr(ps, polygon_mtx);
|
|
|
|
ras.add_path(tr);
|
|
agg::render_scanlines_aa(ras, sl, rb, sa, sg);
|
|
|
|
agg::ellipse e1(m_image_cx, m_image_cy, 5, 5, 20);
|
|
agg::ellipse e2(m_image_cx, m_image_cy, 2, 2, 20);
|
|
agg::conv_stroke<agg::ellipse> c1(e1);
|
|
|
|
rs.color(agg::rgba(0.7,0.8,0));
|
|
ras.add_path(e1);
|
|
agg::render_scanlines(ras, sl, rs);
|
|
|
|
rs.color(agg::rgba(0,0,0));
|
|
ras.add_path(c1);
|
|
agg::render_scanlines(ras, sl, rs);
|
|
|
|
ras.add_path(e2);
|
|
agg::render_scanlines(ras, sl, rs);
|
|
|
|
agg::render_ctrl(ras, sl, rb, m_polygon_angle);
|
|
agg::render_ctrl(ras, sl, rb, m_polygon_scale);
|
|
agg::render_ctrl(ras, sl, rb, m_image_angle);
|
|
agg::render_ctrl(ras, sl, rb, m_image_scale);
|
|
agg::render_ctrl(ras, sl, rb, m_rotate_polygon);
|
|
agg::render_ctrl(ras, sl, rb, m_rotate_image);
|
|
agg::render_ctrl(ras, sl, rb, m_example);
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
virtual void on_mouse_button_down(int x, int y, unsigned flags)
|
|
{
|
|
if(flags & agg::mouse_left)
|
|
{
|
|
if(sqrt((x - m_image_cx) * (x - m_image_cx) +
|
|
(y - m_image_cy) * (y - m_image_cy) ) < 5.0)
|
|
{
|
|
m_dx = x - m_image_cx;
|
|
m_dy = y - m_image_cy;
|
|
m_flag = 1;
|
|
}
|
|
else
|
|
{
|
|
agg::rasterizer_scanline_aa<> ras;
|
|
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(), m_polygon_scale.value());
|
|
polygon_mtx *= agg::trans_affine_translation(m_polygon_cx, m_polygon_cy);
|
|
|
|
agg::path_storage ps;
|
|
create_star(ps);
|
|
|
|
agg::conv_transform<agg::path_storage> tr(ps, polygon_mtx);
|
|
ras.add_path(tr);
|
|
if(ras.hit_test(x, y))
|
|
{
|
|
m_dx = x - m_polygon_cx;
|
|
m_dy = y - m_polygon_cy;
|
|
m_flag = 2;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
virtual void on_mouse_move(int x, int y, unsigned flags)
|
|
{
|
|
if(flags & agg::mouse_left)
|
|
{
|
|
if(m_flag == 1)
|
|
{
|
|
m_image_cx = x - m_dx;
|
|
m_image_cy = y - m_dy;
|
|
force_redraw();
|
|
}
|
|
|
|
if(m_flag == 2)
|
|
{
|
|
m_polygon_cx = x - m_dx;
|
|
m_polygon_cy = y - m_dy;
|
|
force_redraw();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
on_mouse_button_up(x, y, flags);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
virtual void on_mouse_button_up(int x, int y, unsigned flags)
|
|
{
|
|
m_flag = 0;
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------
|
|
virtual void on_ctrl_change()
|
|
{
|
|
if(m_rotate_polygon.status() || m_rotate_image.status())
|
|
{
|
|
wait_mode(false);
|
|
}
|
|
else
|
|
{
|
|
wait_mode(true);
|
|
}
|
|
force_redraw();
|
|
}
|
|
|
|
//------------------------------------------------------------------------
|
|
virtual void on_idle()
|
|
{
|
|
bool redraw = false;
|
|
if(m_rotate_polygon.status())
|
|
{
|
|
m_polygon_angle.value(m_polygon_angle.value() + 0.5);
|
|
if(m_polygon_angle.value() >= 180.0)
|
|
{
|
|
m_polygon_angle.value(m_polygon_angle.value() - 360.0);
|
|
}
|
|
redraw = true;
|
|
}
|
|
|
|
if(m_rotate_image.status())
|
|
{
|
|
m_image_angle.value(m_image_angle.value() + 0.5);
|
|
if(m_image_angle.value() >= 180.0)
|
|
{
|
|
m_image_angle.value(m_image_angle.value() - 360.0);
|
|
}
|
|
redraw = true;
|
|
}
|
|
|
|
if(redraw) force_redraw();
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
int agg_main(int argc, char* argv[])
|
|
{
|
|
the_application app(pix_format, flip_y);
|
|
app.caption("Image Affine Transformations with filtering");
|
|
|
|
const char* img_name = "spheres";
|
|
if(argc >= 2) img_name = argv[1];
|
|
if(!app.load_img(0, img_name))
|
|
{
|
|
char buf[256];
|
|
if(strcmp(img_name, "spheres") == 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(app.rbuf_img(0).width(),
|
|
app.rbuf_img(0).height(),
|
|
0))
|
|
{
|
|
return app.run();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|