agg/examples/gradient_focal.cpp

253 lines
8.1 KiB
C++

#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_span_allocator.h"
#include "agg_span_gradient.h"
#include "agg_gradient_lut.h"
#include "agg_gamma_lut.h"
#include "agg_span_interpolator_linear.h"
#include "ctrl/agg_slider_ctrl.h"
#include "platform/agg_platform_support.h"
#define AGG_BGR24
#include "pixel_formats.h"
enum { flip_y = true };
class the_application : public agg::platform_support
{
typedef agg::renderer_base<pixfmt> renderer_base;
typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_solid;
typedef agg::gamma_lut<agg::int8u, agg::int8u> gamma_lut_type;
typedef agg::gradient_radial_focus gradient_func_type;
typedef agg::gradient_reflect_adaptor<gradient_func_type> gradient_adaptor_type;
typedef agg::gradient_lut<agg::color_interpolator<agg::srgba8>, 1024> color_func_type;
typedef agg::span_interpolator_linear<> interpolator_type;
typedef agg::span_allocator<color_type> span_allocator_type;
typedef agg::span_gradient<color_type,
interpolator_type,
gradient_adaptor_type,
color_func_type> span_gradient_type;
agg::slider_ctrl<color_type> m_gamma;
agg::scanline_u8 m_scanline;
agg::rasterizer_scanline_aa<> m_rasterizer;
span_allocator_type m_alloc;
color_func_type m_gradient_lut;
gamma_lut_type m_gamma_lut;
double m_mouse_x, m_mouse_y;
double m_old_gamma;
public:
the_application(agg::pix_format_e format, bool flip_y) :
agg::platform_support(format, flip_y),
m_gamma(5.0, 5.0, 340.0, 12.0, !flip_y),
m_mouse_x(200), m_mouse_y(200)
{
m_gamma.range(0.5, 2.5);
m_gamma.value(1.0);
m_gamma.label("Gamma = %.3f");
add_ctrl(m_gamma);
m_gamma.no_transform();
m_gamma_lut.gamma(m_gamma.value());
m_old_gamma = m_gamma.value();
build_gradient_lut();
}
virtual void on_init()
{
m_mouse_y = initial_height() / 2;
m_mouse_x = initial_width() / 2;
}
void build_gradient_lut()
{
m_gradient_lut.remove_all();
m_gradient_lut.add_color(0.0, agg::rgba8_gamma_dir(agg::srgba8(0, 255, 0), m_gamma_lut));
m_gradient_lut.add_color(0.2, agg::rgba8_gamma_dir(agg::srgba8(120, 0, 0), m_gamma_lut));
m_gradient_lut.add_color(0.7, agg::rgba8_gamma_dir(agg::srgba8(120, 120, 0), m_gamma_lut));
m_gradient_lut.add_color(1.0, agg::rgba8_gamma_dir(agg::srgba8(0, 0, 255), m_gamma_lut));
//m_gradient_lut.add_color(0.0, agg::srgba8::from_wavelength(380, m_gamma.value()));
//m_gradient_lut.add_color(0.1, agg::srgba8::from_wavelength(420, m_gamma.value()));
//m_gradient_lut.add_color(0.2, agg::srgba8::from_wavelength(460, m_gamma.value()));
//m_gradient_lut.add_color(0.3, agg::srgba8::from_wavelength(500, m_gamma.value()));
//m_gradient_lut.add_color(0.4, agg::srgba8::from_wavelength(540, m_gamma.value()));
//m_gradient_lut.add_color(0.5, agg::srgba8::from_wavelength(580, m_gamma.value()));
//m_gradient_lut.add_color(0.6, agg::srgba8::from_wavelength(620, m_gamma.value()));
//m_gradient_lut.add_color(0.7, agg::srgba8::from_wavelength(660, m_gamma.value()));
//m_gradient_lut.add_color(0.8, agg::srgba8::from_wavelength(700, m_gamma.value()));
//m_gradient_lut.add_color(0.9, agg::srgba8::from_wavelength(740, m_gamma.value()));
//m_gradient_lut.add_color(1.0, agg::srgba8::from_wavelength(780, m_gamma.value()));
m_gradient_lut.build_lut();
}
virtual void on_draw()
{
pixfmt pixf(rbuf_window());
renderer_base rb(pixf);
renderer_solid rs(rb);
rb.clear(agg::rgba(1, 1, 1));
// When Gamma changes rebuild the gamma and gradient LUTs
//------------------
if(m_old_gamma != m_gamma.value())
{
m_gamma_lut.gamma(m_gamma.value());
build_gradient_lut();
m_old_gamma = m_gamma.value();
}
// Gradient center. All gradient functions assume the
// center being in the origin (0,0) and you can't
// change it. But you can apply arbitrary transformations
// to the gradient (see below).
//------------------
double cx = initial_width() / 2;
double cy = initial_height() / 2;
double r = 100;
// Focal center. Defined in the gradient coordinates,
// that is, with respect to the origin (0,0)
//------------------
double fx = m_mouse_x - cx;
double fy = m_mouse_y - cy;
gradient_func_type gradient_func(r, fx, fy);
gradient_adaptor_type gradient_adaptor(gradient_func);
agg::trans_affine gradient_mtx;
// Making the affine matrix. Move to (cx,cy),
// apply the resizing transformations and invert
// the matrix. Gradients and images always assume the
// inverse transformations.
//------------------
gradient_mtx.translate(cx, cy);
gradient_mtx *= trans_affine_resizing();
gradient_mtx.invert();
interpolator_type span_interpolator(gradient_mtx);
span_gradient_type span_gradient(span_interpolator,
gradient_adaptor,
m_gradient_lut,
0, r);
// Form the simple rectangle
//------------------
m_rasterizer.reset();
m_rasterizer.move_to_d(0,0);
m_rasterizer.line_to_d(width(), 0);
m_rasterizer.line_to_d(width(), height());
m_rasterizer.line_to_d(0, height());
// Render the gradient to the whole screen and measure the time
//------------------
start_timer();
agg::render_scanlines_aa(m_rasterizer, m_scanline, rb, m_alloc, span_gradient);
double tm = elapsed_time();
// Draw the transformed circle that shows the gradient boundary
//------------------
agg::ellipse e(cx, cy, r, r);
agg::conv_stroke<agg::ellipse> estr(e);
agg::conv_transform<
agg::conv_stroke<
agg::ellipse> > etrans(estr, trans_affine_resizing());
m_rasterizer.add_path(etrans);
agg::render_scanlines_aa_solid(m_rasterizer, m_scanline, rb, agg::rgba(1,1,1));
// Show the gradient time
//------------------
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, 35.0);
t.text(buf);
m_rasterizer.add_path(pt);
agg::render_scanlines_aa_solid(m_rasterizer, m_scanline, rb, agg::rgba(0,0,0));
// Show the controls
//------------------
agg::render_ctrl(m_rasterizer, m_scanline, rb, m_gamma);
// Apply the inverse gamma to the whole buffer
// (transform the colors to the perceptually uniform space)
//------------------
pixf.apply_gamma_inv(m_gamma_lut);
}
virtual void on_mouse_move(int x, int y, unsigned flags)
{
if(flags & agg::mouse_left)
{
m_mouse_x = x;
m_mouse_y = y;
trans_affine_resizing().inverse_transform(&m_mouse_x, &m_mouse_y);
force_redraw();
}
}
virtual void on_mouse_button_down(int x, int y, unsigned flags)
{
if(flags & agg::mouse_left)
{
m_mouse_x = x;
m_mouse_y = y;
trans_affine_resizing().inverse_transform(&m_mouse_x, &m_mouse_y);
force_redraw();
}
}
};
int agg_main(int argc, char* argv[])
{
the_application app(pix_format, flip_y);
app.caption("AGG Example. PDF linear and radial gradients");
if(app.init(600, 400, agg::window_resize))
{
return app.run();
}
return 1;
}