只有0-255级的alpha通道

> 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) ?


你可能感兴趣的:(Alpha,agg,通道)