我正在寻找某种公式或算法来确定给定RGB值的颜色的亮度。我知道这不像把RGB值加在一起那么简单,更高的总和更亮,但我有点不知所措,不知道从哪里开始。
当前回答
基于所有这些答案,我的简单结论是,对于大多数实际用例,您只需要:
brightness = 0.2*r + 0.7*g + 0.1*b
当r,g,b值在0到255之间时,亮度范围也在0(=黑)到255(=白)之间。
可以对它进行微调,但通常没有必要。
其他回答
方法可以根据您的需要而有所不同。以下是计算亮度的3种方法:
亮度(某些颜色空间的标准):(0.2126*R + 0.7152*G + 0.0722*B)光源 亮度(感知选项1):(0.299*R + 0.587*G + 0.114*B)光源 亮度(感知选项2,计算较慢):根号(0.241*R^2 + 0.691*G^2 + 0.068*B^2)→根号(0.299*R^2 + 0.587*G^2 + 0.114*B^2)(感谢@MatthewHerbst)来源
[编辑:添加了使用命名css颜色的例子,按每种方法排序。]
The inverse-gamma formula by Jive Dadson needs to have the half-adjust removed when implemented in Javascript, i.e. the return from function gam_sRGB needs to be return int(v*255); not return int(v*255+.5); Half-adjust rounds up, and this can cause a value one too high on a R=G=B i.e. grey colour triad. Greyscale conversion on a R=G=B triad should produce a value equal to R; it's one proof that the formula is valid. See Nine Shades of Greyscale for the formula in action (without the half-adjust).
正如@Nils Pipenbrinck所提到的:
所有这些方程在实践中都很有效,但如果你需要非常精确,你就必须[做一些额外的gamma东西]。在深灰色中,忽略伽玛和正确伽玛之间的亮度差异高达20%。
这里有一个完全自包含的JavaScript函数,它做了“额外的”工作来获得额外的准确性。它基于Jive Dadson对这个问题的c++回答。
// Returns greyscale "brightness" (0-1) of the given 0-255 RGB values
// Based on this C++ implementation: https://stackoverflow.com/a/13558570/11950764
function rgbBrightness(r, g, b) {
let v = 0;
v += 0.212655 * ((r/255) <= 0.04045 ? (r/255)/12.92 : Math.pow(((r/255)+0.055)/1.055, 2.4));
v += 0.715158 * ((g/255) <= 0.04045 ? (g/255)/12.92 : Math.pow(((g/255)+0.055)/1.055, 2.4));
v += 0.072187 * ((b/255) <= 0.04045 ? (b/255)/12.92 : Math.pow(((b/255)+0.055)/1.055, 2.4));
return v <= 0.0031308 ? v*12.92 : 1.055 * Math.pow(v,1.0/2.4) - 0.055;
}
请参阅Myndex的答案以获得更准确的计算。
这里有一小段C代码,可以正确地计算可感知的亮度。
// reverses the rgb gamma
#define inverseGamma(t) (((t) <= 0.0404482362771076) ? ((t)/12.92) : pow(((t) + 0.055)/1.055, 2.4))
//CIE L*a*b* f function (used to convert XYZ to L*a*b*) http://en.wikipedia.org/wiki/Lab_color_space
#define LABF(t) ((t >= 8.85645167903563082e-3) ? powf(t,0.333333333333333) : (841.0/108.0)*(t) + (4.0/29.0))
float
rgbToCIEL(PIXEL p)
{
float y;
float r=p.r/255.0;
float g=p.g/255.0;
float b=p.b/255.0;
r=inverseGamma(r);
g=inverseGamma(g);
b=inverseGamma(b);
//Observer = 2°, Illuminant = D65
y = 0.2125862307855955516*r + 0.7151703037034108499*g + 0.07220049864333622685*b;
// At this point we've done RGBtoXYZ now do XYZ to Lab
// y /= WHITEPOINT_Y; The white point for y in D65 is 1.0
y = LABF(y);
/* This is the "normal conversion which produces values scaled to 100
Lab.L = 116.0*y - 16.0;
*/
return(1.16*y - 0.16); // return values for 0.0 >=L <=1.0
}
基于所有这些答案,我的简单结论是,对于大多数实际用例,您只需要:
brightness = 0.2*r + 0.7*g + 0.1*b
当r,g,b值在0到255之间时,亮度范围也在0(=黑)到255(=白)之间。
可以对它进行微调,但通常没有必要。