The best modern way to quantify the difference between two colors is by using the Delta E (ΔE) formulas. These formulas calculate the perceptual difference between two colors in the CIELAB (LAB) color space, which is designed to be more aligned with human vision. These algorithms represent the hard work of the International Commission on Illumination (CIE).
The source code is written to be as performant as possible and will likely outperform other packages. This is achieved by:
- Precomputing and caching heavy constants (eg. 25^7)
- Branchless code (using
%instead ofif elsestatements) - Reduced arithmetic operations (eg. using
x * xinstead ofMath.pow(x, 2)) - Keeping code unrolled instead of calling small helper functions for simple conversions
npm i deltae-js
# or
pnpm add deltae-js
# or
bun add deltae-jsimport { getDeltaE_CIE76, getDeltaE_CMC, getDeltaE_CIE94, getDeltaE_CIEDE2000, type LAB } from 'deltae-js'
// Create two LAB colors to compare
const x1: LAB = [36, 60, 41]
const x2: LAB = [100, 40, 90]
// 1976 formula
getDeltaE_CIE76(x1, x2)
// 1984 formula
getDeltaE_CMC(x1, x2)
// 1994 formula
getDeltaE_CIE94(x1, x2)
// 2000 formula
getDeltaE_CIEDE2000(x1, x2)import type { CMC, CIE94, CIEDE2000 } from 'deltae-js'
const weights_CMC: CMC = {
lightness: 1.35,
chroma: 1.5,
}
getDeltaE_CMC(x1, x2, weights_CMC)
const weights_CIE94: CIE94 = {
lightness: 2, // 1 = Graphic Arts | 2 = Textiles
chroma: 1.25,
hue: 1.5,
}
getDeltaE_CIE94(x1, x2, weights_CIE94)
const weights_CIEDE2000: CIEDE2000 = {
lightness: 1.25,
chroma: 1.5,
hue: 1.75,
}
getDeltaE_CIEDE2000(x1, x2, weights_CIEDE2000)CIELAB (commonly referred to as LAB) is a perceptually uniform color space defined by the International Commission on Illumination (CIE). Unlike RGB, which is device-dependent, LAB is device-independent and designed to approximate human vision.
In the LAB model:
- L* represents lightness (0 = black, 100 = white)
- a* represents the green–red axis (-128 = green, 127 = red)
- b* represents the blue–yellow axis (-128 = blue, 127 = yellow)
Because LAB is perceptually uniform, the numerical distance between two colors in this space better reflects how different they appear to the human eye. This makes LAB particularly suitable for:
- Color difference calculations (ΔE formulas)
- Color sorting and clustering
- Image processing and color analysis
To convert colors from RGB (or other formats) to LAB, you can use the color-convert package:
npm i color-convert
# or
pnpm add color-convert
# or
bun add color-convertThe getDeltaE_fromRGB function returns the ΔE of the input RGB colors.
import convert, { type RGB, type LAB } from 'color-convert'
import { getDeltaE_CIEDE2000 } from 'deltae-js'
const getDeltaE_fromRGB = (a: RGB, b: RGB) => {
const x1: LAB = convert.rgb.lab.raw(a) // Use .raw() to avoid rounding!
const x2: LAB = convert.rgb.lab.raw(b)
return getDeltaE_CIEDE2000(x1, x2)
}
const a: RGB = [255, 192, 63]
const b: RGB = [192, 63, 255]
getDeltaE_fromRGB(a, b) // 70.5183071276013The output of the getDeltaE functions are properly tested using Vitest.
Tests may be run with one of the following commands:
npm test
# or
pnpm test
# or
bun run test