Hi there,
I have worked on the bug #105568
(http://bugzilla.gnome.org/show_bug.cgi?id=105568) and I now have a
solution that I'm going to explain here, in order to have some
feedback.
First, some background. To get a taste of the bug, get a look at the
comment 26 which describe more direct way to observe it
(http://bugzilla.gnome.org/show_bug.cgi?id=105568#c26). The problem is
of the same nature as the one described in the comment 4 of another
related bug: http://bugzilla.gnome.org/show_bug.cgi?id=70335#c4.
The problem is in the file "app/paint-funcs/paint-funcs.c", function
"replace_inten_pixels". In this function, the blending of the colors
is done incorrectly. It doesn't take into account the alpha channel,
and assumes that the values are premultiplied. The solution is simply
the multiplied the components by their alpha values and then to
re-separate the alpha channel.
Below is a more detailed description so that you can make some
paper-test with particular value to see that is correspond to the
desired behaviour.
I already program this patch and it works fine for replace_intensity,
I don't really understand the simplification made in replace_indexed,
so I didn't touch it. My code still need some optimization. I'm
waiting for your feedback before posting my pre-patch in bugzilla to
prevent useless comment that have no change to be taken into account.
Thank you,
Luidnel
**** DETAILED DESCRIPTION ****
So if we use the notation:
- (a1,c1) to describe the alpha channel, and a particular component of
the color of the original content
- (a2,c2) for the new content that should replace the old one
- (ar,cr) for the result
- m the product of the opacity and the mask
- every thing between 0 and 1 (instead of 0 - 255)
The current code is:
ar = m.a2 + (1-m).a1
cr = m.c2 + (1-m).c1
With m = 0.5, you obtain:
ar = (a1 + a2) / 2
cr = (c1 + c2) / 2
which is precisely the case considered in the comment 4 of the other bug.
As described in this comment, the normal computation should be:
ar = m.a2 + (1-m).a1
cr = (m.a2.c2 + (1-m).a1.c1) / ar
With m = 0.5, you obtain:
ar = (a1 + a2) / 2
cr = (a1.c1 + a2.c2) / (a1 + a2)
Using this formula, the computation of the normal composition and
replace composition only differ in the computation of the new alpha.
This new alpha is used in the computation of the components (r, g and
b), so in fact, the result is really different, but the computation is
quite the same.
One can only check that you obtain (a2,c2) if the mask is 1, and
(a1,c1) is the mask is 0, whatever are the values of a1 and a2. This
is not the case for the normal blending because if a2 < 1, then you
can not obtain (a2,c2) for result.