agg/examples/image_alpha.cpp

252 lines
6.7 KiB
C++

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "agg_ellipse.h"
#include "agg_trans_affine.h"
#include "agg_conv_transform.h"
#include "agg_rendering_buffer.h"
#include "agg_span_allocator.h"
#include "agg_span_image_filter_rgb.h"
#include "agg_image_accessors.h"
#include "agg_span_interpolator_linear.h"
#include "agg_span_converter.h"
#include "agg_scanline_u.h"
#include "agg_renderer_scanline.h"
#include "agg_rasterizer_scanline_aa.h"
#include "ctrl/agg_spline_ctrl.h"
#include "platform/agg_platform_support.h"
#define AGG_BGR24
#include "pixel_formats.h"
enum flip_y_e { flip_y = true };
namespace agg
{
//--------------------------------------------------------------------
class span_conv_brightness_alpha
{
public:
typedef int8u alpha_type;
enum array_size_e
{
array_size = 256 * 3
};
span_conv_brightness_alpha(const alpha_type* alpha_array) :
m_alpha_array(alpha_array)
{
}
void prepare() {}
void generate(color_type* span, int x, int y, unsigned len) const
{
do
{
// It's a bit of a hack, but we can treat the 8-bit alpha value as a cover.
color_type::calc_type x = span->r + span->g + span->b;
cover_type cover = m_alpha_array[int(x * array_size / (3 * color_type::full_value()))];
span->a = color_type::mult_cover(color_type::full_value(), cover);
++span;
}
while(--len);
}
private:
const alpha_type* m_alpha_array;
};
}
class the_application : public agg::platform_support
{
agg::spline_ctrl<color_type> m_alpha;
double m_x[50];
double m_y[50];
double m_rx[50];
double m_ry[50];
color_type m_colors[50];
public:
the_application(agg::pix_format_e format, bool flip_y) :
agg::platform_support(format, flip_y),
m_alpha(2, 2, 200, 30, 6, !flip_y)
{
m_alpha.value(0, 1.0);
m_alpha.value(1, 1.0);
m_alpha.value(2, 1.0);
m_alpha.value(3, 0.5);
m_alpha.value(4, 0.5);
m_alpha.value(5, 1.0);
m_alpha.update_spline();
add_ctrl(m_alpha);
}
virtual ~the_application()
{
}
virtual void on_init()
{
unsigned i;
for(i = 0; i < 50; i++)
{
m_x[i] = rand() % int(width());
m_y[i] = rand() % int(height());
m_rx[i] = rand() % 60 + 10;
m_ry[i] = rand() % 60 + 10;
m_colors[i] = agg::srgba8(rand() & 0xFF,
rand() & 0xFF,
rand() & 0xFF,
rand() & 0xFF);
}
}
virtual void on_draw()
{
typedef agg::renderer_base<pixfmt> renderer_base;
pixfmt pixf(rbuf_window());
renderer_base rb(pixf);
rb.clear(agg::rgba(1.0, 1.0, 1.0));
agg::trans_affine src_mtx;
src_mtx *= agg::trans_affine_translation(-initial_width()/2, -initial_height()/2);
src_mtx *= agg::trans_affine_rotation(10.0 * agg::pi / 180.0);
src_mtx *= agg::trans_affine_translation(initial_width()/2, initial_height()/2);
src_mtx *= trans_affine_resizing();
agg::trans_affine img_mtx = src_mtx;
img_mtx.invert();
typedef agg::span_allocator<color_type> span_alloc;
unsigned i;
unsigned char brightness_alpha_array[agg::span_conv_brightness_alpha::array_size];
for(i = 0; i < agg::span_conv_brightness_alpha::array_size; i++)
{
brightness_alpha_array[i] =
agg::int8u(m_alpha.value(double(i) /
double(agg::span_conv_brightness_alpha::array_size)) * 255.0);
}
agg::span_conv_brightness_alpha color_alpha(brightness_alpha_array);
typedef agg::image_accessor_clip<pixfmt> img_source_type;
typedef agg::span_interpolator_linear<> interpolator_type;
typedef agg::span_image_filter_rgb_bilinear<img_source_type,
interpolator_type> span_gen;
typedef agg::span_converter<span_gen,
agg::span_conv_brightness_alpha> span_conv;
span_alloc sa;
interpolator_type interpolator(img_mtx);
pixfmt img_pixf(rbuf_img(0));
img_source_type img_src(img_pixf, agg::rgba(0,0,0,0));
span_gen sg(img_src, interpolator);
span_conv sc(sg, color_alpha);
agg::ellipse ell;
agg::rasterizer_scanline_aa<> ras;
agg::scanline_u8 sl;
for(i = 0; i < 50; i++)
{
ell.init(m_x[i], m_y[i], m_rx[i], m_ry[i], 50);
ras.add_path(ell);
agg::render_scanlines_aa_solid(ras, sl, rb, m_colors[i]);
}
ell.init(initial_width() / 2.0,
initial_height() / 2.0,
initial_width() / 1.9,
initial_height() / 1.9, 200);
agg::conv_transform<agg::ellipse> tr(ell, src_mtx);
ras.add_path(tr);
agg::render_scanlines_aa(ras, sl, rb, sa, sc);
agg::render_ctrl(ras, sl, rb, m_alpha);
}
virtual void on_key(int x, int y, unsigned key, unsigned flags)
{
if(key == ' ')
{
FILE* fd = fopen(full_file_name("alpha"), "w");
int i;
for(i = 0; i < agg::span_conv_brightness_alpha::array_size; i++)
{
int alpha =
agg::int8u(m_alpha.value(double(i) /
double(agg::span_conv_brightness_alpha::array_size)) * 255.0);
if(i % 32 == 0) fprintf(fd, "\n");
fprintf(fd, "%3d, ", alpha);
}
fclose(fd);
}
}
};
int agg_main(int argc, char* argv[])
{
the_application app(pix_format, flip_y);
app.caption("Image Affine Transformations with Alpha-function");
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(), agg::window_resize))
{
return app.run();
}
return 0;
}