avp / spectra

A Javascript color library. Quickly manipulate and convert colors.
avp.github.io/spectra
MIT License
237 stars 18 forks source link

The luminance value is calculated incorrectly #28

Open Azeirah opened 7 years ago

Azeirah commented 7 years ago

According to the w3c on luminance, luminance gets calculated differently to Spectra's current implementation.

the relative brightness of any point in a colorspace, normalized to 0 for darkest black and 1 for lightest white Note 1: For the sRGB colorspace, the relative luminance of a color is defined as L = 0.2126 * R + 0.7152 * G + 0.0722 * B where R, G and B are defined as: if RsRGB <= 0.03928 then R = RsRGB/12.92 else R = ((RsRGB+0.055)/1.055) ^ 2.4 if GsRGB <= 0.03928 then G = GsRGB/12.92 else G = ((GsRGB+0.055)/1.055) ^ 2.4 if BsRGB <= 0.03928 then B = BsRGB/12.92 else B = ((BsRGB+0.055)/1.055) ^ 2.4 and RsRGB, GsRGB, and BsRGB are defined as: RsRGB = R8bit/255 GsRGB = G8bit/255 BsRGB = B8bit/255

Spectra interprets this block of text as

Spectra.fn.prototype.luma = function() {
  return (0.2126 * this.red()) + (0.7152 * this.green()) + (0.0722 * this.blue());
};

But doesn't take into account the if statements.

An example implementation, outside of spectra but supporting spectra objects is as follows:

function relativeLuminance(color) {
    // the relative brightness of any point in a colorspace, normalized to 0 for darkest black and 1 for lightest white
    // Note 1: For the sRGB colorspace, the relative luminance of a color is defined as L = 0.2126 * R + 0.7152 * G + 0.0722 * B where R, G and B are defined as:
    //     if RsRGB <= 0.03928 then R = RsRGB/12.92 else R = ((RsRGB+0.055)/1.055) ^ 2.4
    //     if GsRGB <= 0.03928 then G = GsRGB/12.92 else G = ((GsRGB+0.055)/1.055) ^ 2.4
    //     if BsRGB <= 0.03928 then B = BsRGB/12.92 else B = ((BsRGB+0.055)/1.055) ^ 2.4
    // and RsRGB, GsRGB, and BsRGB are defined as:
    //     RsRGB = R8bit/255
    //     GsRGB = G8bit/255
    //     BsRGB = B8bit/255
    // https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef

    // convert spectra object into {r, g, b} object
    if (color.color) color = color.color;

    var RsRGB = color.r / 255;
    var GsRGB = color.g / 255;
    var BsRGB = color.b / 255;

    var R = RsRGB <= 0.03928 ? RsRGB / 12.92 : Math.pow((RsRGB + 0.055) / 1.055, 2.4);
    var G = GsRGB <= 0.03928 ? GsRGB / 12.92 : Math.pow((GsRGB + 0.055) / 1.055, 2.4);
    var B = BsRGB <= 0.03928 ? BsRGB / 12.92 : Math.pow((BsRGB + 0.055) / 1.055, 2.4);

    var luminance = 0.2126 * R + 0.7152 * G + 0.0722 * B;

    return luminance;
}