I see these values around a lot for converting RGB to luminance or gray... But these (.299,0.587,0.114) coefficients are incorrect....
// 'El Wrongo No Bueno!
do-not-let gray = red * 0.299 + green * 0.587 + blue * 0.114 // Nnnoooooooo
they relate to the obsolete NTSC broadcast system, and don't fit with sRGB.
The current default standard is sRGB which uses HDTV (Rec709) primaries. BUT ALSO you need to linearize (remove gamma/TRC) first!!!!
Here is a one line convert to grayscale: Convert 0-255 sRGB to 0.0-1.0, apply 2.2 exponent, multiply by coefficient, sum, apply reverse exponent, multiply by 255, clamp.
// ANDY'S DOWN AND DIRTY GRAYSCALE™
// Rs Gs Bs are 0-255 sRGB values, tested for recent (2021) browsers.
// For purists: Yea this is NOT the IEC piecewise, it's the simple, hence 'down and dirty'
let gray = Math.min(255,((Rs/255.0)**2.2*0.2126+(Gs/255.0)**2.2*0.7152+(Bs/255.0)**2.2*0.0722)**0.4545*255);
The above is not the piecewise transform, it's intended as a "simple as possible" one line sRGB to Gray 0-255. You can make it a string or sRGB(gray) number as:
// gray to string
let sGrayStr = '#' + gray + gray + gray;
// gray to number
let sGrayNum = gray << 16 | gray << 8 | gray ;
One result of my last few years of research into human visual perception has been the creation of the Advanced Perceptual Contrast Algorithm for WCAG_3 (Silver).
While research continues, the public beta APCA npm package is now available: apca-w3
npm i apca-w3
And the API is trivially simple: send it two colors, it returns a signed INT of the Lc value (lightness contrast).
Lc = APCAcontrast( sRGBtoY( textColor ), sRGBtoY( backgroundColor ) );
Color sent to the linearizing function sRGBtoY()
is a simple rgba array as in [255,255,255,1.0]
There is also a parsing function colorParsley() that can take a 3 or 6 character hex string #fff
or a3b3d4
(hash # is optional but not required), a named CSS color (such as aquamarine
), as rgb(99,122,14)
, or as a number 0x123456
or 15213412
. Text color first, background color second — do not swap colors, as use case affects results. light text on a dark background returns a negative value.
For questions and comments please visit the main APCA repo discussion area.
Thank you!
Andy