Skip to content

Instantly share code, notes, and snippets.

@Daniel-Walsh
Forked from mnpenner/color.ts
Created April 24, 2023 05:49
Show Gist options
  • Save Daniel-Walsh/57c8713b99e505484f0fda270c6e89fc to your computer and use it in GitHub Desktop.
Save Daniel-Walsh/57c8713b99e505484f0fda270c6e89fc to your computer and use it in GitHub Desktop.
RGB color hex to lightness
// based on https://stackoverflow.com/a/56678483/65387
type RGB = [r: number, g: number, b: number]
const UNK = 255 / 2
/**
* @param hex RGB hex string like "#CCCFDB"
* @returns RGB tuple in [0-255]
*/
function hexToRgb(hex: string): RGB {
const h = String(hex).replace(/^#/, '')
if(h.length === 3) {
return [
parseRadix(h[0] + h[0], 16, UNK),
parseRadix(h[1] + h[1], 16, UNK),
parseRadix(h[2] + h[2], 16, UNK),
]
}
if(h.length === 6) {
return [
parseRadix(h.slice(0, 2), 16, UNK),
parseRadix(h.slice(2, 4), 16, UNK),
parseRadix(h.slice(4, 6), 16, UNK),
]
}
return [UNK, UNK, UNK]
}
function sRGBtoLin(colorChannel: number) {
// Send this function a decimal sRGB gamma encoded color value
// between 0.0 and 1.0, and it returns a linearized value.
if(colorChannel <= 0.04045) {
return colorChannel / 12.92
}
return Math.pow((colorChannel + 0.055) / 1.055, 2.4)
}
/**
* @param r Red, [0-1]
* @param g Green, [0-1]
* @param b Blue, [0-1]
* @returns Luminance, [0-1]
*/
function rgbToY(r: number, g: number, b: number) {
return 0.2126 * sRGBtoLin(r) + 0.7152 * sRGBtoLin(g) + 0.0722 * sRGBtoLin(b)
}
/**
* Luminance to perceived lightness.
*
* @param Y Luminance, [0-1]
*/
function YtoLstar(Y: number) {
// Send this function a luminance value between 0.0 and 1.0,
// and it returns L* which is "perceptual lightness"
if(Y <= (216 / 24389)) { // The CIE standard states 0.008856 but 216/24389 is the intent for 0.008856451679036
return Y * (24389 / 27) // The CIE standard states 903.3, but 24389/27 is the intent, making 903.296296296296296
}
return Math.pow(Y, (1 / 3)) * 116 - 16
}
/**
* Calculate perceived lightness from RGB hex string.
*
* @param rgb RGB hex string like "#CCCFDB"
* @returns Lightness value, [0-100].
*/
export function rgbHexToLightness(rgb: string) {
const [r, g, b] = hexToRgb(rgb)
return YtoLstar(rgbToY(r / 255, g / 255, b / 255))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment