Formula to determine brightness of RGB color

前端 未结 20 3002
猫巷女王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:44

    The 'V' of HSV is probably what you're looking for. MATLAB has an rgb2hsv function and the previously cited wikipedia article is full of pseudocode. If an RGB2HSV conversion is not feasible, a less accurate model would be the grayscale version of the image.

    0 讨论(0)
  • 2020-11-21 23:44

    Please define brightness. If you're looking for how close to white the color is you can use Euclidean Distance from (255, 255, 255)

    0 讨论(0)
  • 2020-11-21 23:46

    For clarity, the formulas that use a square root need to be

    sqrt(coefficient * (colour_value^2))

    not

    sqrt((coefficient * colour_value))^2

    The proof of this lies in the conversion of a R=G=B triad to greyscale R. That will only be true if you square the colour value, not the colour value times coefficient. See Nine Shades of Greyscale

    0 讨论(0)
  • 2020-11-21 23:50

    To add what all the others said:

    All these equations work kinda well in practice, but if you need to be very precise you have to first convert the color to linear color space (apply inverse image-gamma), do the weight average of the primary colors and - if you want to display the color - take the luminance back into the monitor gamma.

    The luminance difference between ingnoring gamma and doing proper gamma is up to 20% in the dark grays.

    0 讨论(0)
  • 2020-11-21 23:52

    Rather than getting lost amongst the random selection of formulae mentioned here, I suggest you go for the formula recommended by W3C standards.

    Here's a straightforward but exact PHP implementation of the WCAG 2.0 SC 1.4.3 relative luminance and contrast ratio formulae. It produces values that are appropriate for evaluating the ratios required for WCAG compliance, as on this page, and as such is suitable and appropriate for any web app. This is trivial to port to other languages.

    /**
     * Calculate relative luminance in sRGB colour space for use in WCAG 2.0 compliance
     * @link http://www.w3.org/TR/WCAG20/#relativeluminancedef
     * @param string $col A 3 or 6-digit hex colour string
     * @return float
     * @author Marcus Bointon <marcus@synchromedia.co.uk>
     */
    function relativeluminance($col) {
        //Remove any leading #
        $col = trim($col, '#');
        //Convert 3-digit to 6-digit
        if (strlen($col) == 3) {
            $col = $col[0] . $col[0] . $col[1] . $col[1] . $col[2] . $col[2];
        }
        //Convert hex to 0-1 scale
        $components = array(
            'r' => hexdec(substr($col, 0, 2)) / 255,
            'g' => hexdec(substr($col, 2, 2)) / 255,
            'b' => hexdec(substr($col, 4, 2)) / 255
        );
        //Correct for sRGB
        foreach($components as $c => $v) {
            if ($v <= 0.04045) {
                $components[$c] = $v / 12.92;
            } else {
                $components[$c] = pow((($v + 0.055) / 1.055), 2.4);
            }
        }
        //Calculate relative luminance using ITU-R BT. 709 coefficients
        return ($components['r'] * 0.2126) + ($components['g'] * 0.7152) + ($components['b'] * 0.0722);
    }
    
    /**
     * Calculate contrast ratio acording to WCAG 2.0 formula
     * Will return a value between 1 (no contrast) and 21 (max contrast)
     * @link http://www.w3.org/TR/WCAG20/#contrast-ratiodef
     * @param string $c1 A 3 or 6-digit hex colour string
     * @param string $c2 A 3 or 6-digit hex colour string
     * @return float
     * @author Marcus Bointon <marcus@synchromedia.co.uk>
     */
    function contrastratio($c1, $c2) {
        $y1 = relativeluminance($c1);
        $y2 = relativeluminance($c2);
        //Arrange so $y1 is lightest
        if ($y1 < $y2) {
            $y3 = $y1;
            $y1 = $y2;
            $y2 = $y3;
        }
        return ($y1 + 0.05) / ($y2 + 0.05);
    }
    
    0 讨论(0)
  • 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

    0 讨论(0)
提交回复
热议问题