将 RGB 转换为 RGBA 白色
我有一个十六进制颜色,例如 #F4F8FB
(或 rgb(244, 248, 251)
),我想将其转换为尽可能透明的颜色 rgba 颜色(当显示在白色上时)。有道理吗?我正在寻找一种算法,或者至少是一种如何做到这一点的算法的想法。
例如:
rgb( 128, 128, 255 ) --> rgba( 0, 0, 255, .5 )
rgb( 152, 177, 202 ) --> rgba( 50, 100, 150, .5 ) // can be better(lower alpha)
想法?
基于 Guffa 答案的仅供参考的解决方案:
function RGBtoRGBA(r, g, b){
if((g == null) && (typeof r === 'string')){
var hex = r.replace(/^\s*#|\s*$/g, '');
if(hex.length === 3){
hex = hex.replace(/(.)/g, '$1$1');
}
r = parseInt(hex.substr(0, 2), 16);
g = parseInt(hex.substr(2, 2), 16);
b = parseInt(hex.substr(4, 2), 16);
}
var min, a = (255 - (min = Math.min(r, g, b))) / 255;
return {
r : r = 0|(r - min) / a,
g : g = 0|(g - min) / a,
b : b = 0|(b - min) / a,
a : a = (0|1000*a)/1000,
rgba : 'rgba(' + r + ', ' + g + ', ' + b + ', ' + a + ')'
};
}
RGBtoRGBA(204, 153, 102) == RGBtoRGBA('#CC9966') == RGBtoRGBA('C96') ==
{
r : 170,
g : 85 ,
b : 0 ,
a : 0.6,
rgba : 'rgba(170, 85, 0, 0.6)'
}
I have a hex color, e.g. #F4F8FB
(or rgb(244, 248, 251)
) that I want converted into an as-transparent-as-possible rgba color (when displayed over white). Make sense? I'm looking for an algorithm, or at least idea of an algorithm for how to do so.
For Example:
rgb( 128, 128, 255 ) --> rgba( 0, 0, 255, .5 )
rgb( 152, 177, 202 ) --> rgba( 50, 100, 150, .5 ) // can be better(lower alpha)
Ideas?
FYI solution based on Guffa's answer:
function RGBtoRGBA(r, g, b){
if((g == null) && (typeof r === 'string')){
var hex = r.replace(/^\s*#|\s*$/g, '');
if(hex.length === 3){
hex = hex.replace(/(.)/g, '$1$1');
}
r = parseInt(hex.substr(0, 2), 16);
g = parseInt(hex.substr(2, 2), 16);
b = parseInt(hex.substr(4, 2), 16);
}
var min, a = (255 - (min = Math.min(r, g, b))) / 255;
return {
r : r = 0|(r - min) / a,
g : g = 0|(g - min) / a,
b : b = 0|(b - min) / a,
a : a = (0|1000*a)/1000,
rgba : 'rgba(' + r + ', ' + g + ', ' + b + ', ' + a + ')'
};
}
RGBtoRGBA(204, 153, 102) == RGBtoRGBA('#CC9966') == RGBtoRGBA('C96') ==
{
r : 170,
g : 85 ,
b : 0 ,
a : 0.6,
rgba : 'rgba(170, 85, 0, 0.6)'
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
取最低的颜色分量,并将其转换为 Alpha 值。然后通过减去最低值并除以 Alpha 值来缩放颜色分量。
示例:
因此,
rgb(152, 177, 202)
显示为rgba(0, 62, 123, .404)
。我已经在 Photoshop 中验证了颜色确实完美匹配。
Take the lowest color component, and convert that to an alpha value. Then scale the color components by subtracting the lowest, and dividing by the alpha value.
Example:
So,
rgb(152, 177, 202)
displays asrgba(0, 62, 123, .404)
.I have verified in Photoshop that the colors actually match perfectly.
设 r、g 和 b 为输入值,r'、g'、b' 和 a' 为输出值,全部缩放(目前,因为它使数学更漂亮)在 1 和 0 之间。然后,通过叠加颜色的公式:
1 - a' 项代表背景贡献,其他项代表前景。做一些代数:
直观上,似乎最小颜色值将成为问题的限制因素,因此将其绑定到 m:
将相应的输出值 m' 设置为零,因为我们希望最大化透明度:
所以, javascript(从 1 翻译到 255):
请注意,我假设 a' 在这里是不透明度的。将其更改为透明度很简单 - 只需从 a' 的公式中删除“1 -”即可。需要注意的另一件事是,这似乎不会产生准确的结果 - 它表示上面给出的示例的不透明度为 0.498 (128, 128, 255)。然而,这已经非常接近了。
Let r, g, and b be the input values and r', g', b', and a' be the output values, all scaled (for now, as it makes the math prettier) between 1 and 0. Then, by the formula for overlaying colors:
The 1 - a' terms represent the background contribution, and the other terms represent the foreground. Do some algebra:
Intuitively, it seems that the minimum color value will be the limiting factor in the problem, so bind this to m:
Set the corresponding output value, m', to zero, as we want to maximize transparency:
So, in javascript (translating from 1 to 255 along the way):
Note that I'm assuming that a' is opacity here. It is trivial to change it to transparency - just remove the "1 -" from the formula for a'. Anothing thing to note is that this does not seem to produce exact results - it said that the opacity was 0.498 for the example you gave above (128, 128, 255). However, this is extremely close.
我会考虑 RGB<->HSL 转换。即发光度==白色量==透明度量。
对于您的示例
rgb( 128, 128, 255 )
,我们需要首先将 RGB 值移动到0
最大量,即rgb( 0, 0, 128 )
- 这将是我们的颜色,其中白色尽可能少。之后,使用亮度公式,我们计算需要添加到深色中以获得原始颜色的白色量 - 这将是我们的 alpha:希望这是有道理的。 :)
I'd look to RGB<->HSL conversion. I.e. luminosity == amount of white == amount of transparency.
For your example
rgb( 128, 128, 255 )
, we need to shift RGB values to0
first by maximum amount, i.e. torgb( 0, 0, 128 )
- that would be our color with as few of white as possible. And after that, using formula for luminance, we calculate amount of white we need to add to our dark color to get original color - that would be our alpha:Hope that makes sense. :)
对于那些使用 SASS/SCSS 的人,我编写了一个小型 SCSS 函数,以便您可以轻松使用 @Guffa 描述的算法
For those of you using SASS/SCSS, I've wrote a small SCSS function so you can easily use the algorithm described by @Guffa
我只是描述算法的一个想法,没有完整的解决方案:
基本上,你有三个数字
x
、y
、z
并且你是寻找 [0 范围内的三个新数字x'
、y'
、z'
和乘数a
,1] 这样:这以通道也采用范围内的值的单位编写[0,1]。在 8 位离散值中,它会是这样的:
此外,您想要最大的可能值
a
。你可以解:等等。在实数值中,这有无限多个解,只需代入任何实数
a
,但问题是找到一个离散化误差最小的数字。I'm just describing an idea for the algorithm, no full solution:
Basically, you have three numbers
x
,y
,z
and you are looking for three new numbersx'
,y'
,z'
and a multipliera
in the range [0,1] such that:This is written in units where the channels also take values in the range [0,1]. In 8bit discrete values, it'd be something like this:
Moreover, you want the largest possible value
a
. You can solve:Etc. In real values this has infinitely many solutions, just plug in any real number
a
, but the problem is to find a number for which the discretization error is minimal.这应该可以做到:
This should do it:
对于低颜色成分,最重要的答案对我不起作用。例如,如果颜色为#80000,则它不会计算正确的 alpha。从技术上讲,它应该使其成为 alpha 0.5 的#ff0000。要解决这个问题,您需要使用 RGB ->福胜利-> RGBA 转换。这是获取正确值的伪代码:
“newRgb”将包含新调整颜色的值并使用“alpha”变量来控制透明度。
The top answer didn't work for me with low color components. For example it does not calculate correct alpha if color is #80000. Technically it should make it into #ff0000 with alpha 0.5. To resolve this, you need to use RGB -> HSL -> RGBA conversion. This is pseudo code to get the correct values:
"newRgb" will contain the value of the new adjusted color and use "alpha" variable to control the transparency.