Formula to determine brightness of RGB color

前端 未结 20 3139
猫巷女王i
猫巷女王i 2020-11-21 23:16

I\'m looking for some kind of formula or algorithm to determine the brightness of a color given the RGB values. I know it can\'t be as simple as adding the RGB values toget

20条回答
  •  眼角桃花
    2020-11-21 23:54

    The "Accepted" Answer is Incorrect and Incomplete

    The only answers that are accurate are the @jive-dadson and @EddingtonsMonkey answers, and in support @nils-pipenbrinck. The other answers (including the accepted) are linking to or citing sources that are either wrong, irrelevant, obsolete, or broken.

    Briefly:

    • sRGB must be LINEARIZED before applying the coefficients.
    • Luminance (L or Y) is linear as is light.
    • Perceived lightness (L*) is nonlinear as is human perception.
    • HSV and HSL are not even remotely accurate in terms of perception.
    • The IEC standard for sRGB specifies a threshold of 0.04045 it is NOT 0.03928 (that was from an obsolete early draft).
    • The be useful (i.e. relative to perception), Euclidian distances require a perceptually uniform Cartesian vector space such as CIELAB. sRGB is not one.

    What follows is a correct and complete answer:

    Because this thread appears highly in search engines, I am adding this answer to clarify the various misconceptions on the subject.

    Brightness is a perceptual attribute, it does not have a direct measure.

    Perceived lightness is measured by some vision models such as CIELAB, here L* (Lstar) is a measure of perceptual lightness, and is non-linear to approximate the human vision non-linear response curve.

    Luminance is a linear measure of light, spectrally weighted for normal vision but not adjusted for non-linear perception of lightness.

    Luma ( prime) is a gamma encoded, weighted signal used in some video encodings. It is not to be confused with linear luminance.

    Gamma or transfer curve (TRC) is a curve that is often similar to the perceptual curve, and is commonly applied to image data for storage or broadcast to reduce perceived noise and/or improve data utilization (and related reasons).

    To determine perceived lightness, first convert gamma encoded R´G´B´ image values to linear luminance (L or Y ) and then to non-linear perceived lightness (L*)


    TO FIND LUMINANCE:

    ...Because apparently it was lost somewhere...

    Step One:

    Convert all sRGB 8 bit integer values to decimal 0.0-1.0

      vR = sR / 255;
      vG = sG / 255;
      vB = sB / 255;
    

    Step Two:

    Convert a gamma encoded RGB to a linear value. sRGB (computer standard) for instance requires a power curve of approximately V^2.2, though the "accurate" transform is:

    Where V´ is the gamma-encoded R, G, or B channel of sRGB.
    Pseudocode:

    function sRGBtoLin(colorChannel) {
            // 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;
            } else {
                return pow((( colorChannel + 0.055)/1.055),2.4));
            }
        }
    

    Step Three:

    To find Luminance (Y) apply the standard coefficients for sRGB:

    Pseudocode using above functions:

    Y = (0.2126 * sRGBtoLin(vR) + 0.7152 * sRGBtoLin(vG) + 0.0722 * sRGBtoLin(vB))
    

    TO FIND PERCEIVED LIGHTNESS:

    Step Four:

    Take luminance Y from above, and transform to L*


    Pseudocode:

    function YtoLstar(Y) {
            // 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
            } else {
                return pow(Y,(1/3)) * 116 - 16;
            }
        }
    

    L* is a value from 0 (black) to 100 (white) where 50 is the perceptual "middle grey". L* = 50 is the equivalent of Y = 18.4, or in other words an 18% grey card, representing the middle of a photographic exposure (Ansel Adams zone V).

    References:

    IEC 61966-2-1:1999 Standard
    Wikipedia sRGB
    Wikipedia CIELAB
    Wikipedia CIEXYZ
    Charles Poynton's Gamma FAQ

提交回复
热议问题