[cairo] Premultiplied transparency causes streaks in images
paril at alteredsoftworks.com
Fri Nov 12 02:32:49 PST 2010
The fixed code you provided outputs a single dot (you forgot the Paint()
call, but I extrapolated), which appears fine when you look at it at face
value, but again, if you re-add that loop I had in the first place you see
the transparency around the corners of the circle creating black streaks.
This is the problem.
If you weren't able to see the output, here it is:
Here's a slightly modified version with no y modification. This shows you
the clear black outline when the brush is continuously drawn in one spot:
I don't entirely understand your explanation; the only time you can really
tell that it's happening is when you are drawing a bunch of lines around,
hence why in the example I drew a capsule shape.
...which replaces the PaintWithAlpha operation with a
> multiplication of the source alpha
Actually, PaintWithAlpha was my second attempt at fixing the original code,
which DID multiply the source alpha. I thought maybe the problem was because
I was not using PaintWithAlpha, which appeared not to be the case.
On Fri, Nov 12, 2010 at 5:20 AM, Andrea Canciani <ranma42 at gmail.com> wrote:
> On Fri, Nov 12, 2010 at 10:46 AM, Paril <paril at alteredsoftworks.com>
> > Here, I just threw this together very very quickly in C#; it CLEARLY
> > the output "streaking" black transparent pixels down the purple brush
> > stroke, when the expected output should show a complete purple circle
> > the same color on the inside of the capsule-like shape.
> > http://alteredsoftworks.com/cairo/streaking.txt
> > It should be rather easy to convert to C/C++. I used no .NET-specific
> > classes; DevIL for the image loading and Cairo for the drawing, just as I
> > use in the actual program.
> > The reason I suspect premultiplication is because the only time these
> > streaks can be created is when the background transparency is turned from
> > white to black - which is done by multiplying the color values by their
> > alpha. If all of the images' alpha and color values remain, when they are
> > blended they should not create any streaks at all.
> Observation: your code is (should be, as I'm unable to test it) equivalent
> to the attached one, which replaces the PaintWithAlpha operation with a
> multiplication of the source alpha
> The problem is caused by color quantization (and amplified by
> In your case:
> Brush color: ARGB = (0.16, 0.42, 0.7, 1) -> [40, 17, 28, 40] premultiplied
> Where the brush image is opaque, you actually get this values, but where it
> is not, you end up with smaller values, for example:
> Image alpha: 15 (in 8 bit integer) -> [2, 1, 1, 2] (or something like that)
> When you composite multiple times this pixel over itself you would expect
> the original color, you obviously will get something very different
> (something like: 40, 20, 20, 40, if my example computations were correct).
> I think that integer formats are not well suited for repeated compositing
> of the
> same image as they obviously break the assumption:
> n*color OVER clear == color OVER^n clear
> which you seem to rely on.
> NB: this would be a problem with nonpremultiplied as well, but it would be
> harder to notice (because it would only affect alpha, instead of both alpha
> Example: (assuming 8-bit nonpremultiplied compositing)
> Start color: opaque red (1, 0, 0, 1) = [255, 0, 0, 255]
> Use it with a very light brush (1/1000), so that the color becomes [0,
> 0, 0, 255]
> Even if you composite it 1000 times, you don't get opaque red.
> I hope I managed to guess what is the real issue.
> I'm not sure as I'm unable to test it, but it would be be confirmed if
> the attachment streaking-working.txt (or something along that lines) worked
> (or at least showed much less artifacts).
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the cairo