不透明度のある「同等の」色を見つける


92

背景色に「リボン」が別の単色で表示されているとします。ここで、リボンを部分的に透明にして、細部をブレンドできるようにしますが、それでもリボンを背景上で「同じ色」に保ちます。

リボンの色の100%未満の特定の不透明度/アルファについて、背景の不透明度が100%の色と同じである必要があるRGB値を(簡単に)決定する方法はありますか?

これが写真です。背景はrgb(72, 28, 97)、リボンrgb(45, 34, 70)です。rgba(r, g, b, a)この無地と同じように見えるようにリボンにaが欲しいです。

ここに画像の説明を入力してください


1
非常によく似た質問がここにあります:stackoverflow.com/questions/6672374/convert-rgb-rgbaですが、主な違いは、この質問は白の基本色を指定しているのに対し、これは任意です。
–BoltClock

回答:


129

カラーブレンディングは、チャネルごとの線形補間ですよね?したがって、計算は非常に簡単です。RGB2よりもRGBA1を使用している場合、RGB3の効果的な視覚的結果は次のようになります。

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

…ここで、アルファチャネルは0.0から1.0です。

サニティチェック:アルファが0の場合、RGB3はRGB2と同じですか?はい。アルファが1の場合、RGB3はRGB1と同じですか?はい。

背景色と最終色のみをロックダウンした場合、要件を満たすことができるRGBA色(無限、浮動小数点空間内)が多数あります。したがって、バーの色または必要な不透明度レベルのいずれかを選択し、もう一方の値を見つける必要があります。

アルファに基づいて色を選ぶ

RGB3(最終的に必要な色)、RGB2(背景色)、およびA1(必要な不透明度)がわかっていて、RGB1を探しているだけの場合は、次のように方程式を再配置できます。

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

理論的には可能ですが、標準のRGBA範囲では不可能な色の組み合わせがいくつかあります。たとえば、背景が真っ黒で、知覚される色が真っ白で、アルファが1%の場合、次のことが必要になります。

r1 = g1 = b1 = 255/0.01 = 25500

…他のどの製品よりも100倍明るい超高輝度の白。

色に基づいてアルファを選ぶ

RGB3(最終的に必要な色)、RGB2(背景色)、およびRGB1(不透明度を変更したい色)がわかっていて、A1を探しているだけの場合は、を再配置できます。したがって、方程式:

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

これらが異なる値を与える場合、それを正確に一致させることはできませんが、アルファを平均して可能な限り近づけることができます。たとえば、赤の上に緑を重ねて青にする不透明度は世界にはありません。


、、そしてまた不明r1g1はありませんb1か?
エリック

@Ericわからない。既知のアルファレベルとそうでない色の場合に備えて、回答を編集しました。
Phrogz 2012

ヘッズアップ、私はPhotoshopで最初の3つの数式を使用して、他の唯一の参照色が白の場合に0.8アルファでどの色になるかを見つけました...を見つけるために1 +(1-a)または1.2を使用する必要がありました右の色...
ジョン・ウィリアム・ドミンゴ

1
@Phrogz私はあなたの「アルファに基づいて色を選ぶ」方程式を使用しています、そして私は赤チャンネルのために負の数(-31)を取得します。赤の値として負の値を使用すると、赤の値として0を使用した場合と同じ結果が得られます。このネガを使用可能なものに変換する方法はありますか?ここで何が起こっているかについての手がかりはありますか?
nocturno 2016

たぶん私の計算はずれていますが、RGB3 =#163920、RGB2 = #FFFFFF、およびA1 = 0.92の場合、この式は予期しない結果を生成します。計算されたRGB1 = rgb(2、40、13)ですが、rgba(2、40、13、0.92)=#15381Fであり、#163920ではありません。
thdoan 2016

12

Phrogzの答えを使ってLESSミックスインを作りました。入力:

  1. 色はどのように見えるべきか
  2. 特定のアルファで
  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:白){$ r3:赤($ desired_colour); $ g3:緑($ Desired_colour); $ b3:blue($ Desired_colour); $ r2:赤($ background_colour); $ g2:緑($ 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; 背景色:$ desired_colour; 背景色:rgba($ r1、$ g1、$ b1、$ Desired_alpha); }
metaColin 2015

2
SCSSバージョンのミックスインを採用して作りました。ここでデモとコードを見つけてください:codepen.io/Grienauer/pen/Grogdx
Grienauer 2017

@Grienauer私はまったく同じことをしました、あなたがすでにそれを共有していることに気づいていませんでした!私の唯一の違いは、背景色をデフォルトで白にしたことです
tehlivi 2018

7

おかげPhrogzさんとephemerの偉大な答えは、ここにいることSASS機能で自動的に最高同等のRGBAカラーを計算します。

目的の色と既存の背景を使用して呼び出すと、各RGBコンポーネントの±1/256以内で目的の結果が得られる最良の(最も透明な)同等のRGBA色が計算されます(丸め誤差のため)。

@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
FYI、この関数はとしてスタイラスに存在するtransparentify()stylus-lang.com/docs/bifs.html#transparentifytop-bottom-alpha ...私はスタイラスに手動でこれを移植した後に発見された...
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を選択すると、RGB1 = RGB3が必要であることがわかりますが、アルファ0を選択しても、解決策は得られません(明らかに)。


1

これまでに見つけた最も実用的な解決策は、カラーピッカーツールを使用して結果の色を測定し、測定した色をオーバーレイに使用することです。この方法では、完全な色の一致が得られます。

さまざまなミックスインを使用してみましたが、丸め誤差のため、肉眼で違いを確認できました。


1
OPはおそらく動的に決定を下す方法を望んでいましたが、それは具体的に述べられておらず、あなたの答えは静的な色/アルファの選択に良いハックを与えます。
エリックノウルズ

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);
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.