-
Notifications
You must be signed in to change notification settings - Fork 756
Description
In section 8.3, some of the example RGB color values that correspond to HWB colors appear to be incorrect. For example, hwb(0, 100%, 20%) is translated to #d4d5d5 when in fact (because whiteness + blackness > 100%) it should be the grayscale value #d5d5d5.
I think this is caused by floating-point rounding errors. If you naively normalize the input arguments and pass them to the hwbToRgb function, you get:
hwbToRgb(0, 1/1.2, 0.2/1.2)
= [0.8333333333333333, 0.8333333333333334, 0.8333333333333334]
hwbToRgb(0, 1/1.2, 0.2/1.2).map(c => c * 255)
= [212.49999999999997, 212.5, 212.5]
hwbToRgb(0, 1/1.2, 0.2/1.2).map(c => c * 255).map(Math.round)
= [212, 213, 213]
This is because floating-point inaccuracies cause the term 1 - white - black to return -5.551115123125783e-17 rather than 0, so the hslToRgb() result's red channel isn't fully canceled out and ends up skewing the result. In pure math, though, the correct channel values would all be 212.5 which would all round to 213, producing the color #d5d5d5.
It may be worth solving this issue for implementers who copy the hwbToRgb() function by including the whiteness/blackness normalization logic in the function itself:
function hwbToRgb(hue, white, black) {
if (white + black >= 1) {
var gray = white / (white + black);
return [gray, gray, gray];
}
var rgb = hslToRgb(hue, 1, .5);
for(var i = 0; i < 3; i++) {
rgb[i] *= (1 - white - black);
rgb[i] += white;
}
return rgb;
}