> Only you don't see it, because the > color_alpha->calculate > function just always returns *covers. In my case, I > was using > a combined alpha (source x shape)... Ah, I see. Well, the division by 255 is too expensive. The usual technique there is to add 128 to the intermediate result: v + (((r - v) * alpha + 0x80) >> 8); But it also requires the alpha to be in range 0...256 (not 255), so that it's not an easy issue, because I use 0...255. Besides, sometimes I use precalculated alpha in range 0...255*255. The very same issue is applicable to the calculation of the color_alpha->calculate(). Anyway, you can try to play with these formulas and I'd appreciate if someone could help me to systematize these things.
> The problem is with the bilinear filter. I implemented > it separately from the general arbitrary filtering > algorithm because it works about 40% faster. But if > you take the "image_filters" example and play with it > you will see that the bilinear filter darkenes the > image. Well, the image_filters example would have the same problem I witnessed in my case; pixel_formats_rgb24_image::span does the same kind of shifting, I guess. Only you don't see it, because the color_alpha->calculate function just always returns *covers. In my case, I was using a combined alpha (source x shape)...
Well, the problem is even worse than just "speed up" (BTW, it doesn't matter much because the most time consuming code is interpolation itself) The problem is with the bilinear filter. I implemented it separately from the general arbitrary filtering algorithm because it works about 40% faster. But if you take the "image_filters" example and play with it you will see that the bilinear filter darkenes the image. Then if you comment out "case 1" /* case 1: { typedef agg::image_transform_attr<agg::null_distortions, agg::null_color_alpha, agg::null_gradient_alpha> attr_type; typedef agg::span_null_interpolator<attr_type> span_interpolator; typedef
agg::pixfmt_bgr24_image_bilinear<attr_type> span_renderer; typedef agg::renderer_scanline<span_interpolator, span_renderer> renderer; agg::null_distortions distortions; agg::null_color_alpha color_alpha; agg::null_gradient_alpha gradient_alpha; attr_type attr(rbuf_img(1), img_mtx, distortions, color_alpha, gradient_alpha); renderer ri(rbuf_img(0)); ri.attribute(attr); ras.add_path(tr); ras.render(ri); } break; */
nd uncomment // case 1: below, the bilinear interpolation will be done through the general method. In this case everything is fine. I honestly don't know why, but there's something wrong with rounding off, that is, the probability of rounding to the floor is higher than to the ceiling. Perhaps I should use the array of the precalculated weights rather than compute them on demand.
I have been playing with the image transform classes, specifically with the code in agg_pixfmt_rgba32_image.h, and I have noticed a few problems with the code you are using to handle the alpha values. There are often places where you multiply values ranging from 0 to 255, but then, finally, divide them by 256 (>> 8). Here is an example of what I have observed. In method agg::pixel_formats_rgba32_image_bilinear::span, using class agg::image_alpha_rgba8 as an alpha provider, if I step through the code, I see that : - image_subpixel_mask = 0xff - weight = 0xfe01 - fg[3] = 0xfe02ff (source alpha was 0xff) after fg[3] >>= image_subpixel_shift * 2, - fg[3] = 0xfe; // should be 0xff if divided by 0xff*0xff - alpha is the calculated on this base : 0xff * 0xfe => 0xfd02 0xfd02 >> 8 => 0xfd
so I end up with alpha = 253 rather than 255, and all the nice speed-up code (alpha == 255) doesn't get executed, and some noise gets added to the output. Any idea how to fix this in an elegant way (I could just decrease the threshold for which alpha is considered 100% opaque) ?