#include #include #include "agg_pixfmt_rgb24.h" #include "agg_renderer_base.h" #include "agg_renderer_scanline.h" #include "agg_scanline_u.h" #include "agg_rasterizer_scanline_aa.h" #include "agg_ellipse.h" #include "agg_span_gradient.h" #include "agg_span_interpolator_linear.h" enum { frame_width = 320, frame_height = 200 }; // Writing the buffer to a .PPM file, assuming it has // RGB-structure, one byte per color component //-------------------------------------------------- bool write_ppm(const unsigned char* buf, unsigned width, unsigned height, const char* file_name) { FILE* fd = fopen(file_name, "wb"); if(fd) { fprintf(fd, "P6 %d %d 255 ", width, height); fwrite(buf, 1, width * height * 3, fd); fclose(fd); return true; } return false; } // A simple function to form the gradient color array // consisting of 3 colors, "begin", "middle", "end" //--------------------------------------------------- void fill_color_array(agg::rgba8* array, agg::rgba8 begin, agg::rgba8 middle, agg::rgba8 end) { unsigned i; for(i = 0; i < 128; ++i) { array[i] = begin.gradient(middle, i / 128.0); } for(; i < 256; ++i) { array[i] = middle.gradient(end, (i - 128) / 128.0); } } int main() { unsigned char* buffer = new unsigned char[frame_width * frame_height * 3]; agg::rendering_buffer rbuf(buffer, frame_width, frame_height, -frame_width * 3); // Pixel format and basic renderers. //----------------- typedef agg::pixfmt_rgb24 pixfmt_type; typedef agg::renderer_base renderer_base_type; // Gradient shape function (linear, radial, custom, etc) //----------------- typedef agg::gradient_x gradient_func_type; // Span interpolator. This object is used in all span generators // that operate with transformations during iterating of the spans, // for example, image transformers use the interpolator too. //----------------- typedef agg::span_interpolator_linear<> interpolator_type; // Span allocator is an object that allocates memory for // the array of colors that will be used to render the // color spans. One object can be shared between different // span generators. //----------------- typedef agg::span_allocator span_allocator_type; // Finally, the gradient span generator working with the agg::rgba8 // color type. // The 4-th argument is the color function that should have // the [] operator returning the color in range of [0...255]. // In our case it will be a simple look-up table of 256 colors. //----------------- typedef agg::span_gradient span_gradient_type; // The gradient scanline renderer type //----------------- typedef agg::renderer_scanline_aa renderer_gradient_type; // Common declarations (pixel format and basic renderer). //---------------- pixfmt_type pixf(rbuf); renderer_base_type rbase(pixf); // The gradient objects declarations //---------------- gradient_func_type gradient_func; // The gradient function agg::trans_affine gradient_mtx; // Affine transformer interpolator_type span_interpolator(gradient_mtx); // Span interpolator span_allocator_type span_allocator; // Span Allocator agg::rgba8 color_array[256]; // The gradient colors // Declare the gradient span itself. // The last two arguments are so called "d1" and "d2" // defining two distances in pixels, where the gradient starts // and where it ends. The actual meaning of "d1" and "d2" depands // on the gradient function. //---------------- span_gradient_type span_gradient(span_allocator, span_interpolator, gradient_func, color_array, 0, 100); // The gradient renderer //---------------- renderer_gradient_type ren_gradient(rbase, span_gradient); // The rasterizing/scanline stuff //---------------- agg::rasterizer_scanline_aa<> ras; agg::scanline_u8 sl; // Finally we can draw a circle. //---------------- rbase.clear(agg::rgba8(255, 255, 255)); fill_color_array(color_array, agg::rgba8(0,50,50), agg::rgba8(240, 255, 100), agg::rgba8(80, 0, 0)); agg::ellipse ell(50, 50, 50, 50, 100); ras.add_path(ell); agg::render(ras, sl, ren_gradient); write_ppm(buffer, frame_width, frame_height, "agg_test.ppm"); delete [] buffer; return 0; } /* ------------------------------ Step 1. gradients1.png ------------------------------ Step 2. // Declare the gradient span itself. // The last two arguments are so called "d1" and "d2" // defining two distances in pixels, where the gradient starts // and where it ends. The actual meaning of "d1" and "d2" depands // on the gradient function. //---------------- span_gradient_type span_gradient(span_allocator, span_interpolator, gradient_func, color_array, 50, 100); gradients2.png ------------------------------ Step 3. // Gradient shape function (linear, radial, custom, etc) //----------------- typedef agg::gradient_circle gradient_func_type; // . . . // Declare the gradient span itself. // The last two arguments are so called "d1" and "d2" // defining two distances in pixels, where the gradient starts // and where it ends. The actual meaning of "d1" and "d2" depands // on the gradient function. //---------------- span_gradient_type span_gradient(span_allocator, span_interpolator, gradient_func, color_array, 0, 100); // . . . agg::ellipse ell(0, 0, 120, 120, 100); gradients3.png ------------------------------ Step 4. // Declare the gradient span itself. // The last two arguments are so called "d1" and "d2" // defining two distances in pixels, where the gradient starts // and where it ends. The actual meaning of "d1" and "d2" depands // on the gradient function. //---------------- span_gradient_type span_gradient(span_allocator, span_interpolator, gradient_func, color_array, 50, 100); gradients4.png ------------------------------ Step 5. gradient_mtx *= agg::trans_affine_scaling(0.75, 1.2); gradient_mtx *= agg::trans_affine_rotation(-agg::pi/3.0); gradient_mtx *= agg::trans_affine_translation(100.0, 100.0); gradient_mtx.invert(); agg::ellipse ell(100, 100, 120, 120, 100); gradients5.png ------------------------------ Step 6. Return to the original code // Calculate the affine transformation matrix for the linear gradient // from (x1, y1) to (x2, y2). gradient_d2 is the "base" to scale the // gradient. Here d1 must be 0.0, and d2 must equal gradient_d2. //--------------------------------------------------------------- void calc_linear_gradient_transform(double x1, double y1, double x2, double y2, agg::trans_affine& mtx, double gradient_d2 = 100.0) { double dx = x2 - x1; double dy = y2 - y1; mtx.reset(); mtx *= agg::trans_affine_scaling(sqrt(dx * dx + dy * dy) / gradient_d2); mtx *= agg::trans_affine_rotation(atan2(dy, dx)); mtx *= agg::trans_affine_translation(x1, y1); mtx.invert(); } agg::ellipse ell(100, 100, 120, 120, 100); gradients6.png */