查找不透明的“等效”颜色


92

假设我有一个背景色,上面有一个“色带”,以另一种纯色运行。现在,我希望功能区是部分透明的,以使某些细节融合在一起,但仍要使功能区在背景上保持“相同颜色”。

对于给定的不透明度/ alpha <100%的色带,是否有一种方法可以轻松地确定与背景具有100%不透明度的RGB值应相同的RGB值?

这是一张照片。背景是rgb(72, 28, 97)丝带rgb(45, 34, 70)。我想要一个rgba(r, g, b, a)功能区,以便它看起来与此纯色相同。

在此处输入图片说明


1
可以在这里找到一个非常相似的问题:stackoverflow.com/questions/6672374/convert-rgb-rgba,但主要区别在于该问题指定了白色的底色,而这个是任意的。
BoltClock

Answers:


129

色彩混合只是每个通道的线性插值,对吗?所以数学很简单。如果RGBA1超过RGB2,则有效的视觉结果RGB3将为:

r3 = r2 + (r1-r2)*a1
g3 = g2 + (g1-g2)*a1
b3 = b2 + (b1-b2)*a1

…alpha通道从0.0到1.0。

完整性检查:如果alpha为0,则RGB3是否与RGB2相同?是。如果alpha为1,RGB3是否与RGB1相同?是。

如果仅锁定背景色和最终色,则可以满足要求的大量RGBA颜色(在浮点空间中是无限的)。因此,您必须选择条形的颜色或所需的不透明度级别,然后找出另一个的值。

根据Alpha挑选颜色

如果您知道RGB3(最终所需的颜色),RGB2(背景色)和A1(所需的不透明度),而您只是在寻找RGB1,那么我们可以这样重新排列方程式:

r1 = (r3 - r2 + r2*a1)/a1
g1 = (g3 - g2 + g2*a1)/a1
b1 = (b3 - b2 + b2*a1)/a1

有一些颜色组合在理论上是可能的,但是在标准RGBA范围内是不可能的。例如,如果背景为纯黑色,所需的感知颜色为纯白色,所需的Alpha为1%,则您需要:

r1 = g1 = b1 = 255/0.01 = 25500

…超亮的白色,比任何其他产品都要亮100倍。

根据颜色选择Alpha

如果您知道RGB3(最终所需的颜色),RGB2(背景颜色)和RGB1(要更改其不透明度的颜色),而您只是在寻找A1,那么我们可以重新安排因此,等式:

a1 = (r3-r2) / (r1-r2)
a1 = (g3-g2) / (g1-g2)
a1 = (b3-b2) / (b1-b2)

如果它们给出不同的值,那么您将无法使其完全匹配,但是您可以平均alpha以使其尽可能接近。例如,世界上没有不透明性会使您将绿色置于红色之上而变为蓝色。


不是r1g1b1也未可知?
埃里克(Eric)

@Eric我不确定。我已经编辑了答案,以防万一是已知的alpha级别而未知的颜色。
Phrogz 2012年

抬起头,我用您的前三个公式在Photoshop中查找当我唯一的其他参考颜色为白色时,0.8 alpha处的颜色是什么...我必须使用1 +(1-a)或1.2才能找到正确的颜色...
约翰·威廉·多明戈

1
@Phrogz我正在使用“基于Alpha选择颜色”等式,红色通道的数值为负数(-31)。当我使用负数作为红色值时,得到的结果与使用0作为红色值时得到的结果相同。有没有办法将这种负面因素转化为有用的东西?关于这里发生的事情有什么线索吗?
Nocturno

也许我的计算已经关闭,但是当RGB3 =#163920,RGB2 = #FFFFFF和A1 = 0.92时,此公式会产生意外结果;计算得出的RGB1 = rgb(2,40,13),但是rgba(2,40,13,0.92)=#15381F,而不是#163920。
thdoan '16

12

我用Phrogz的答案做了一个LESS mixin。您输入:

  1. 颜色应该如何
  2. 具有一定的alpha
  3. 在给定的背景下(默认为白色)

这是代码:

.bg_alpha_calc (@desired_colour, @desired_alpha, @background_colour: white) {
    @r3: red(@desired_colour);
    @g3: green(@desired_colour);
    @b3: blue(@desired_colour);

    @r2: red(@background_colour);
    @g2: green(@background_colour);
    @b2: blue(@background_colour);

    // r1 = (r3 - r2 + r2 * a1) / a1
    @r1: ( @r3 - @r2 + (@r2 * @desired_alpha) ) / @desired_alpha;
    @g1: ( @g3 - @g2 + (@g2 * @desired_alpha) ) / @desired_alpha;
    @b1: ( @b3 - @b2 + (@b2 * @desired_alpha) ) / @desired_alpha;

    background-color: @desired_colour;
    background-color: rgba(@r1, @g1, @b1, @desired_alpha);

}

用法如下:

@mycolour: #abc;
@another_colour: blue;
.box_overlay {
  // example:
  .bg_alpha_calc (@mycolour, 0.97, @another_colour);
  // or (for white bg) just:
  .bg_alpha_calc (@mycolour, 0.97);
}

显然不适用于不可能的组合(如Phrogz所述),这意味着仅支持中等程度的透明度。看看如何使用它。


1
@mixin bg_alpha_calc($ desired_colour,$ desired_alpha,$ background_colour:white){$ r3:红色($ desired_colour); $ g3:绿色($ desired_colour); $ b3:蓝色($ desired_colour); $ r2:红色($ background_colour); $ g2:绿色($ background_colour); $ b2:蓝色($ background_colour); // r1 =(r3-r2 + r2 * a1)/ a1 $ r1:($ r3-$ r2 +($ r2 * $ desired_alpha))/ $ desired_alpha; $ g1:($ g3-$ g2 +($ g2 * $ desired_alpha))/ $ desired_alpha; $ b1:($ b3-$ b2 +($ b2 * $ desired_alpha))/ $ desired_alpha; 背景颜色:$ desired_colour; background-color:rgba($ r1,$ g1,$ b1,$ desired_alpha); }
metaColin

2
我采用了SCSS版本mixin。在此处找到演示和代码:codepen.io/Grienauer/pen/Grogdx
Grienauer

@Grienauer我完全一样,但没有意识到您已经分享了!我唯一的区别是我将背景颜色默认为白色
tehlivi

7

多亏了PhrogzEphemer的出色回答,这是一个SASS函数,可以自动计算出最佳的等效RGBA颜色。

您使用所需的颜色和现有的背景对其进行调用,它将计算出最佳(意味着最透明)的等效RGBA颜色,从而在每个RGB分量的±1/256之内给出所需的结果(由于舍入误差):

@function alphaize($desired-color, $background-color) {

    $r1: red($background-color);
    $g1: green($background-color);
    $b1: blue($background-color);

    $r2: red($desired-color);
    $g2: green($desired-color);
    $b2: blue($desired-color);

    $alpha: 0;
    $r: -1;
    $g: -1;
    $b: -1;

    @while $alpha < 1 and ($r < 0 or $g < 0 or $b < 0
                           or $r > 255 or $g > 255 or $b > 255) {
        $alpha: $alpha + 1/256;
        $inv: 1 / $alpha;
        $r: $r2 * $inv + $r1 * (1 - $inv);
        $g: $g2 * $inv + $g1 * (1 - $inv);
        $b: $b2 * $inv + $b1 * (1 - $inv);
    }

    @return rgba($r, $g, $b, $alpha);
}

我只是将它与多种组合(所有的Bootswatch主题)进行了测试,并且它对暗光和暗光效果均有效。

PS:如果您需要所得颜色的精度优于±1/256,则需要了解在混合rgba颜色时浏览器适用哪种舍入算法(我不知道这是否标准化)并添加合适的条件@while,以使其保持现有状态,$alpha直到达到所需的精度为止。


2
仅供参考,此功能在Stylus中的存在方式为transparentify()stylus-lang.com/docs/bifs.html#transparentifytop-bottom-alpha ...在将其手动移植到Stylus后我发现了……
Weotch

6

从@Phrogz的答案:

r3 = r2 + (r1-r2)*a1
g3 = g2 + (g1-g2)*a1
b3 = b2 + (b1-b2)*a1

所以:

r3 - r2 = (r1-r2)*a1
g3 - g2 = (g1-g2)*a1
b3 - b2 = (b1-b2)*a1

所以:

r1 = (r3 - r2) / a1 + r2
g1 = (g3 - g2) / a1 + g2
b1 = (b3 - b2) / a1 + b2

请注意,您可以挑选任何价值a1,这将找到的相应值r1g1b1需要。例如,选择1的alpha值告诉您需要RGB1 = RGB3,但是选择0的alpha值不会产生任何解决方案(显然)。


1

到目前为止,我发现的最实用的解决方案是:仅使用颜色选择器工具测量所得的颜色,然后将测量的颜色用于覆盖。此方法可提供完美的色彩匹配。

我尝试使用不同的mixins,但是由于舍入错误,我仍然可以用肉眼看到差异


1
OP可能想要一种动态进行确定的方法,但是并没有特别说明,您的答案的确为静态颜色/ alpha选择提供了很好的解决方案。
Erik Knowles

0

要扩展@Tobia的答案并允许指定不透明性,例如transparentify:

@function rgbaMorph($desired-color, $background-color: rgb(255,255,255), $desired-alpha: 0) {

    $r1: red($desired-color);
    $g1: green($desired-color);
    $b1: blue($desired-color);

    $r2: red($background-color);
    $g2: green($background-color);
    $b2: blue($background-color);

    $r: -1;
    $g: -1;
    $b: -1;

    @if ($desired-alpha != 0) {
        $r: ( $r1 - $r2 + ($r2 * $desired-alpha) ) / $desired-alpha;
        $g: ( $g1 - $g2 + ($g2 * $desired-alpha) ) / $desired-alpha;
        $b: ( $b1 - $b2 + ($b2 * $desired-alpha) ) / $desired-alpha;
    }

    @if (($desired-alpha == 0) or ($r < 0 or $g < 0 or $b < 0
                           or $r > 255 or $g > 255 or $b > 255)) {
        //if alpha not attainable, this will find lowest alpha that is

        $alpha: $desired-alpha;
        @while $alpha < 1 and ($r < 0 or $g < 0 or $b < 0
                           or $r > 255 or $g > 255 or $b > 255) {
            $alpha: $alpha + 1/256;
            $inv: 1 / $alpha;
            $r: $r1 * $inv + $r2 * (1 - $inv);
            $g: $g1 * $inv + $g2 * (1 - $inv);
            $b: $b1 * $inv + $b2 * (1 - $inv);
        }
        @debug "Color not attainable at opacity using alpha: " $alpha " instead of: " $desired-alpha;

        $desired-alpha: $alpha;
    }

    @return rgba($r, $g, $b, $desired-alpha);
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.