gdiplus: Fix blend_colors when alpha channel differs.
When picking a color halfway between 100% white (0xffffffff) and fully transparent (0x00000000), the result was 50% opaque 50% grey (0x80808080) when it should really be 50% opaque white (0x80ffffff). This had a tendency to create grey fringes on things. The fix is to weight the non-alpha components based on how much they contribute to the final alpha value.
This commit is contained in:
parent
e95dbb3b74
commit
9c579023f0
|
@ -521,20 +521,22 @@ static GpStatus alpha_blend_pixels(GpGraphics *graphics, INT dst_x, INT dst_y,
|
||||||
|
|
||||||
static ARGB blend_colors(ARGB start, ARGB end, REAL position)
|
static ARGB blend_colors(ARGB start, ARGB end, REAL position)
|
||||||
{
|
{
|
||||||
ARGB result=0;
|
INT start_a, end_a, final_a;
|
||||||
ARGB i;
|
INT pos;
|
||||||
INT a1, a2, a3;
|
|
||||||
|
|
||||||
a1 = (start >> 24) & 0xff;
|
pos = gdip_round(position * 0xff);
|
||||||
a2 = (end >> 24) & 0xff;
|
|
||||||
|
|
||||||
a3 = (int)(a1*(1.0f - position)+a2*(position));
|
start_a = ((start >> 24) & 0xff) * (pos ^ 0xff);
|
||||||
|
end_a = ((end >> 24) & 0xff) * pos;
|
||||||
|
|
||||||
result |= a3 << 24;
|
final_a = start_a + end_a;
|
||||||
|
|
||||||
for (i=0xff; i<=0xff0000; i = i << 8)
|
if (final_a < 0xff) return 0;
|
||||||
result |= (int)((start&i)*(1.0f - position)+(end&i)*(position))&i;
|
|
||||||
return result;
|
return (final_a / 0xff) << 24 |
|
||||||
|
((((start >> 16) & 0xff) * start_a + (((end >> 16) & 0xff) * end_a)) / final_a) << 16 |
|
||||||
|
((((start >> 8) & 0xff) * start_a + (((end >> 8) & 0xff) * end_a)) / final_a) << 8 |
|
||||||
|
(((start & 0xff) * start_a + ((end & 0xff) * end_a)) / final_a);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ARGB blend_line_gradient(GpLineGradient* brush, REAL position)
|
static ARGB blend_line_gradient(GpLineGradient* brush, REAL position)
|
||||||
|
|
Loading…
Reference in New Issue