やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

2色のコントラスト比を算出したい(相対輝度)

 背景色を任意にしつつ、見やすい文字色は白か黒のどちらか。それを算出したい。

成果物

 少数による計算が必要だが、bashでは整数でしか計算できない。ので、pythonで実装した。

情報源

 2色のコントラスト値が4.5以上なら見やすい。4.5以下なら見づらい。

実装をみる

contrast.js

module.exports = (a, b) => {
    // WCAG contrast ratio
    // see http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
    a = new Color(a);
    b = new Color(b);
    const l1 = a.luminance();
    const l2 = b.luminance();
    return l1 > l2 ? (l1 + 0.05) / (l2 + 0.05) : (l2 + 0.05) / (l1 + 0.05);
}

luminance.js

Color.prototype.luminance = function(lum) {
    if (lum !== undefined && type(lum) === 'number') {
        if (lum === 0) {
            // return pure black
            return new Color([0,0,0,this._rgb[3]], 'rgb');
        }
        if (lum === 1) {
            // return pure white
            return new Color([255,255,255,this._rgb[3]], 'rgb');
        }
        // compute new color using...
        let cur_lum = this.luminance();
        let mode = 'rgb';
        let max_iter = MAX_ITER;

        const test = (low, high) => {
            const mid = low.interpolate(high, 0.5, mode);
            const lm = mid.luminance();
            if (Math.abs(lum - lm) < EPS || !max_iter--) {
                // close enough
                return mid;
            }
            return lm > lum ? test(low, mid) : test(mid, high);
        }

        const rgb = (cur_lum > lum ? test(new Color([0,0,0]), this) : test(this, new Color([255,255,255]))).rgb();
        return new Color([...rgb,this._rgb[3]]);
    }
    return rgb2luminance(...(this._rgb).slice(0,3));
}

const rgb2luminance = (r,g,b) => {
    // relative luminance
    // see http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
    r = luminance_x(r);
    g = luminance_x(g);
    b = luminance_x(b);
    return 0.2126 * r + 0.7152 * g + 0.0722 * b;
}

const luminance_x = (x) => {
    x /= 255;
    return x <= 0.03928 ? x/12.92 : pow((x+0.055)/1.055, 2.4);
}

対象環境

$ uname -a
Linux raspberrypi 5.4.83-v7l+ #1379 SMP Mon Dec 14 13:11:54 GMT 2020 armv7l GNU/Linux