摘自:http://article.gmane.org/gmane.comp.graphics.agg/2911/
> I've read the pattern_perspective.cpp sample but I don't understand very > well how to apply a texture on a shape. > Could you explain me the stages to do that and what is the role of each > operation ? Yes, I must admit the example is difficult to read. First, it's better to take pattern_resample.cpp that covers automatic resampling too. Now I'll try to explain to you what to do step by step. 1. If your pattern has actual alpha channel, the pixels must be premultiplied. In general, all image transformers work only with premultiplied colors. If it's RGB or all alphas are 255 you don't need to do anything. But if you load a PNG image you most probably will have to premultiply it. 2. You get your image somehow, create a rendering buffer and pixel format for it: typedef agg::pixfmt_bgra32 pixfmt; typedef agg::pixfmt_bgra32_pre pixfmt_pre; typedef pixfmt::color_type color_type; In the example agg::rendering_buffer is already created in load_img() function: pixfmt img_pixf(rbuf_img(0)); Note that there's no difference if you use pixfmt or pixfmt_pre for the source image. 3. Create a span allocator. It's better to keep it in a class and reuse it instead of creating/destroying. typedef agg::span_allocator<color_type> span_alloc_type; span_alloc_type sa; 4. Create a filter LUT agg::image_filter_bilinear filter_kernel; agg::image_filter_lut filter(filter_kernel, true); For some methods there's no need in it. For example, span_image_filter_rgba_bilinear has hardcoded bilinear filter. 5. Create an image accessor that defines the logic of pixel wrapping. typedef agg::wrap_mode_reflect_auto_pow2 wrap_type; typedef agg::image_accessor_wrap<pixfmt, wrap_type, wrap_type> img_source_type; img_source_type img_src(img_pixf); The possible variants are: image_accessor_clip - clips the pixels outside of the source image and replaces them with a given color. image_accessor_clone - clones the edge pixels. image_accessor_wrap - wraps the pixels (it's what actually creates the repeating pattern) The wrapper has template arguments of, what to do by X and Y: wrap_mode_repeat, wrap_mode_reflect, wrap_mode_repeat_pow2, wrap_mode_reflect_pow2, wrap_mode_repeat_auto_pow2, wrap_mode_reflect_auto_pow2. If the size of your pattern is power of 2, you can use a faster _pow2 version (shifts and masking instead of divisions). 6. Create an interpolator. For affine transformations you can use a fast linear interpolator that operates in integers, with a Bresenham-like algorithm inside. For perspective transformations you can't use linear interpolator. There are two choices: 6.1. exact interpolator: typedef agg::span_interpolator_trans<agg::trans_perspective> interpolator_type; interpolator_type interpolator(tr); Defines an exact interpolator, works slower because it calculates the points on every pixel 6.2. Subdivision approximation: typedef agg::span_interpolator_linear_subdiv<agg::trans_perspective> interpolator_type; interpolator_type interpolator(tr); It calculates every 16'th pixel (configurable) and linearly interpolates between them. Works faster, but on heavily transformed images there is considerable inaccuracy. Also, for transformations with automatic resampling (rather slow, but produces high quality) you need a special version of the interpolator, because you need to know the local scale at every point: 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); 7. Then you create a span generator that does the image filtering job. It can be one of the following: span_image_filter_rgba_nn - nearest neigbor filter (box). Actually, no filtering span_image_filter_rgba_bilinear - hardcoded bilinear filter span_image_filter_rgba_2x2 - arbitrary filter of fixed size 2x2 pixels span_image_filter_rgba - arbitrary filter of any size, like bicubic, gaussian, etc (slow). span_image_resample_rgba_affine - image resampler for affine transformations. It can't be used with perspective transformer. span_image_resample_rgba - image resampler for arbitrary transformer. The interpolator must provide function to calculate (or interpolate) the local scale. 8. Create and configure the transformer. It can be a simple affine transformer, or perspective one, or even some nonlinear, like in distortions.cpp example. The algorithmic feature is that the transformer must be inverse. That is, it should map destination pixels onto source ones. 9. Finally, you feed the rasterizer with an arbitrary path and draw it, for example: g_rasterizer.move_to_d(x1, y1); g_rasterizer.line_to_d(x2, y2); g_rasterizer.line_to_d(x3, y3); g_rasterizer.line_to_d(x4, y4); typedef span_image_filter_rgba_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); The path can be just a rectangle, or quadrilateral, or whatever. The whole point is that it will draw perfectly anti-aliased edges. For example, you can draw a circle with pattern inside. Well, this explanation isn't full, but I hope it will help you together with working pattern_resample.cpp McSeem