如何从两个 RGB 值中找到一种颜色的 RGBA 值?
我有一种预感,这以前已经做过,但我对此完全是外行,不知道如何开始提出正确的问题。所以我将描述我正在尝试做的事情...
我有一个未知的 ARGB 颜色。我只知道它的绝对 RGB 值显示在两种已知的不透明背景颜色上,例如黑色 0x000000 和白色 0xFFFFFF。因此,继续这个例子,如果我知道 ARGB 颜色在显示超过 0x000000 时相当于 RGB 0x000080,并且我知道相同的 ARGB 颜色在显示超过 0xFFFFFF 时相当于 RGB 0x7F7FFF,有没有办法计算原始 ARGB 颜色是?
或者这甚至可能吗???
I have a hunch this has been done before but I am a total layman at this and don't know how to begin to ask the right question. So I will describe what I am trying to do...
I have an unknown ARGB color. I only know its absolute RGB value as displayed over two known opaque background colors, for example black 0x000000 and white 0xFFFFFF. So, to continue the example, if I know that the ARGB color is RGB 0x000080 equivalent when displayed over 0x000000 and I know that the same ARGB color is RGB 0x7F7FFF equivalent when displayed over 0xFFFFFF, is there a way to compute what the original ARGB color is?
Or is this even possible???
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
所以,你知道将 (a,r,g,b) 放在 (r1,g1,b1) 上会得到 (R1,G1,B1),将它放在 (r2,g2,b2) 上会得到 (R2,G2) ,B2)。换句话说——顺便说一句,我将在 a 范围从 0 到 1 的单位中工作——你知道 (1-a)r1+ar=R1、(1-a)r2+ar=R2 等。将这两者相减:得到 (1-a)(r1-r2)=R1-R2,因此 a=1-(R1-R2)/(r1-r2)。一旦你知道了a,你就可以解决其他所有问题。
实际上,您应该计算对所有三个 {R,G,B} 进行计算得到的 a 值,并对它们进行平均或其他处理,以减少舍入误差的影响。事实上,我建议您采用 a = 1 - [(R1-R2)sign(r1-r2) + (G1-G2)sign(g1-g2) + (B1-B2)sign(b1-b2)] / (|r1-r2|+|g1-g2|+|b1-b2),这相当于对更可靠的颜色赋予更高的权重。
现在你有,例如,r = (R1-(1-a)r1)/a = (R2-(1-a)r2)/a。如果 a、r、g、b 具有无限精度值,这两者将是相等的,但当然在实践中它们可能略有不同。将它们平均:r = [(R1+R2)-(1-a)(r1+r2)]/2a。
如果您的 a 值恰好非常小,那么您将只能获得有关 r、g、b 的相当不可靠的信息。 (在 a=0 的限制下,你根本得不到任何信息,而且显然你对此无能为力。)你可能会得到 0..255 范围之外的数字,在这种情况下我不会认为你可以做得比仅仅剪辑更好。
以下是针对您的特定示例的效果。 (r1,g1,b1)=(0,0,0); (r2,g2,b2)=(255,255,255); (R1,G1,B1)=(0,0,128); (R2,G2,B2)=(127,127,255)。所以 a = 1 - [127+127+127]/[255+255+255] = 128/255,这恰好是 a 的 256 个实际可能值之一。 (如果不是,我们可能应该在这个阶段对其进行四舍五入。)
现在 r = (127-255*127/255)*255/256 = 0;同样,g = 0; b = (383-255*127/255)*255/256 = 255。
所以我们的 ARGB 颜色是 80,00,00,FF。
So, you know that putting (a,r,g,b) over (r1,g1,b1) gives you (R1,G1,B1) and that putting it over (r2,g2,b2) gives you (R2,G2,B2). In other words -- incidentally I'm going to work here in units where a ranges from 0 to 1 -- you know (1-a)r1+ar=R1, (1-a)r2+ar=R2, etc. Take those two and subtract: you get (1-a)(r1-r2)=R1-R2 and hence a=1-(R1-R2)/(r1-r2). Once you know a, you can work everything else out.
You should actually compute the values of a you get from doing that calculation on all three of {R,G,B} and average them or something, to reduce the effects of roundoff error. In fact I'd recommend that you take a = 1 - [(R1-R2)sign(r1-r2) + (G1-G2)sign(g1-g2) + (B1-B2)sign(b1-b2)] / (|r1-r2|+|g1-g2|+|b1-b2), which amounts to weighting the more reliable colours more highly.
Now you have, e.g., r = (R1-(1-a)r1)/a = (R2-(1-a)r2)/a. These two would be equal if you had infinite-precision values for a,r,g,b, but of course in practice they may differ slightly. Average them: r = [(R1+R2)-(1-a)(r1+r2)]/2a.
If your value of a happens to be very small then you'll get only rather unreliable information about r,g,b. (In the limit where a=0 you'll get no information at all, and there's obviously nothing you can do about that.) It's possible that you may get numbers outside the range 0..255, in which case I don't think you can do better than just clipping.
Here's how it works out for your particular example. (r1,g1,b1)=(0,0,0); (r2,g2,b2)=(255,255,255); (R1,G1,B1)=(0,0,128); (R2,G2,B2)=(127,127,255). So a = 1 - [127+127+127]/[255+255+255] = 128/255, which happens to be one of the 256 actually-possible values of a. (If it weren't, we should probably round it at this stage.)
Now r = (127-255*127/255)*255/256 = 0; likewise g = 0; and b = (383-255*127/255)*255/256 = 255.
So our ARGB colour was 80,00,00,FF.
选择黑色和白色作为背景颜色是最好的选择,既便于计算又保证结果的准确性。大量滥用符号....
从第一个减去第二个...
因此
且 RGB = (a(RGB))/a = 0x000080/a = 0x0000FF
您可以对其他背景颜色选择执行非常类似的操作。 a 越小,两种背景颜色越接近,确定 RGBA 值的准确度就越低。考虑 A=0 或两个背景颜色相同的极端情况。
Choosing black and white as the background colors is the best choice, both for ease of calculation and accuracy of result. With lots of abuse of notation....
Subtracting the second from the first...
So
and RGB = (a(RGB))/a = 0x000080/a = 0x0000FF
You can do something very similar with other choices of background color. The smaller a is and the closer the two background colors are the less accurately you will be able to determine the RGBA value. Consider the extreme cases where A=0 or where the two background colors are the same.