Subtle colour error

Hi everybody,

it seems that the graphics renderer behaves a bit weird when drawing the same colour over itself with a different alpha value. The best way to reproduce this is this example code:

auto grey = Colour(0xFF333333);

g.fillAll(grey);
g.setColour(grey.withAlpha(0.6f));
g.fillRect(getLocalBounds().reduced(50));

One would expect that the inner rectangle isn’t visible, but here is how it looks:

image

It’s super subtle but if you bump up the contrast in a image editor, you’ll see that this isn’t the same colour . It happens on JUCE 6.1.4, macOS, Windows, regardless of whether OpenGL is active or not.

Seems natural to me that applying a soft touch of a dark grey will effectively darken what’s underneath. Why would you except to see no difference?

Actually I would assume that if I apply a color to itself with a lower alpha it doesn’t change the resulting colour - this is how every image editor works.

Also the resulting colour varies for each alpha value - with 0.7 it’s invisible, but with 0.6 it’s like this - it looks to me more like a rounding error when summing up the colors.

It was reported to me by a user and I don’t think it’s a critical issue, I was just wondering why it happens and why it is so consistently wrong across all configurations.

with alpha values, we’re often working with 8-bit integers. So when premultiplying, we’re gonna often get truncation.

Like in your example, a pixel value of 0x33 (decimal 51). when you premultiply it by 0.6, you get 30.6, which is gonna get rounded to either 30, or 31.
If both the background and the overlayed color get rounded down, or both rounded up, you’re gonna get an error.
On the other hand, if the background get’s rounded down, but the foreground gets rounded up. The error can cancel out. and the image looks ‘correct’.

As my mother always said: “integer fractional arithmetic is like a box of chocolates. You never know what you’re gonna get”.

1 Like

Image editors work in all kinds of color spaces. But in your case it’s just basic weighing and summing (plus clamping and rounding errors as @JeffMcClintock said).