Finden einer „äquivalenten“ Farbe mit Deckkraft

89

Angenommen, ich habe eine Hintergrundfarbe, über die ein "Band" in einer anderen Volltonfarbe läuft. Jetzt möchte ich, dass das Farbband teilweise transparent ist, damit einige Details durchgehen, aber das Farbband über dem Hintergrund immer noch die "gleiche Farbe" hat.

Gibt es eine Möglichkeit, für eine bestimmte Deckkraft / Alpha <100% der Farbbandfarbe (leicht) zu bestimmen, welche RGB-Werte mit ihrer Farbe mit 100% Deckkraft über dem Hintergrund identisch sein müssen?

Hier ist ein Bild. Hintergrund ist rgb(72, 28, 97), Band rgb(45, 34, 70). Ich möchte ein rgba(r, g, b, a)für das Band, damit es mit dieser Volltonfarbe identisch erscheint.

Geben Sie hier die Bildbeschreibung ein

vicvicvic
quelle
1
Eine sehr ähnliche Frage finden Sie hier: stackoverflow.com/questions/6672374/convert-rgb-rgba, aber der Hauptunterschied besteht darin, dass diese Frage eine Grundfarbe von Weiß angibt, während diese willkürlich ist.
BoltClock

Antworten:

124

Farbmischung ist nur eine lineare Interpolation pro Kanal, oder? Die Mathematik ist also ziemlich einfach. Wenn Sie RGBA1 über RGB2 haben, ist das effektive visuelle Ergebnis RGB3:

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

… Wo der Alpha-Kanal zwischen 0,0 und 1,0 liegt.

Sanity Check: Wenn das Alpha 0 ist, ist RGB3 dasselbe wie RGB2? Ja. Wenn das Alpha 1 ist, ist RGB3 dasselbe wie RGB1? Ja.

Wenn Sie nur die Hintergrundfarbe und die endgültige Farbe gesperrt haben, gibt es eine große Anzahl von RGBA-Farben (unendlich, im Gleitkommaraum), die die Anforderungen erfüllen könnten. Sie müssen also entweder die Farbe des Balkens oder die gewünschte Deckkraft auswählen und den Wert des anderen ermitteln.

Auswahl der Farbe basierend auf Alpha

Wenn Sie RGB3 (die endgültige gewünschte Farbe), RGB2 (die Hintergrundfarbe) und A1 (wie viel Deckkraft Sie möchten) kennen und nur nach RGB1 suchen, können wir die Gleichungen folgendermaßen neu anordnen:

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

Es gibt einige Farbkombinationen, die theoretisch möglich, aber angesichts des Standard-RGBA-Bereichs unmöglich sind. Wenn der Hintergrund beispielsweise rein schwarz ist, die gewünschte wahrgenommene Farbe rein weiß ist und das gewünschte Alpha 1% beträgt, benötigen Sie:

r1 = g1 = b1 = 255/0.01 = 25500

… Ein superhelles Weiß 100 × heller als jedes andere.

Auswahl des Alphas anhand der Farben

Wenn Sie RGB3 (die endgültige gewünschte Farbe), RGB2 (die Hintergrundfarbe) und RGB1 (die Farbe, deren Deckkraft Sie variieren möchten) kennen und Sie nur nach A1 suchen, können wir die neu anordnen Gleichungen also:

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

Wenn diese unterschiedliche Werte ergeben, können Sie die Übereinstimmung nicht genau festlegen, aber Sie können die Alphas mitteln, um so nah wie möglich zu kommen. Zum Beispiel gibt es keine Deckkraft auf der Welt, mit der Sie Grün über Rot setzen können, um Blau zu erhalten.

Phrogz
quelle
Ist nicht r1, g1und b1auch nicht bekannt?
Eric
@ Eric Ich bin nicht sicher. Ich habe die Antwort für den Fall bearbeitet, dass die Alpha-Stufe bekannt ist und die Farben nicht.
Phrogz
Kopf hoch, ich habe Ihre ersten drei Formeln in Photoshop verwendet, um herauszufinden, welche Farbe bei 0,8 Alpha liegen würde, wenn meine einzige andere Referenzfarbe Weiß wäre ... Ich musste 1 + (1 - a) oder 1,2 verwenden, um die zu finden richtige Farbe ...
John William Domingo
1
@Phrogz Ich verwende Ihre 'Wählen Sie die Farbe basierend auf Alpha'-Gleichungen und erhalte eine negative Zahl (-31) für den roten Kanal. Wenn ich das Negativ als Rotwert verwende, erhalte ich das gleiche Ergebnis, als hätte ich 0 als Rotwert verwendet. Gibt es eine Möglichkeit, dieses Negativ in etwas Verwendbares umzuwandeln? Irgendeine Ahnung, was hier los ist?
Nocturno
Vielleicht sind meine Berechnungen nicht korrekt, aber diese Formel führt zu einem unerwarteten Ergebnis, wenn RGB3 = # 163920, RGB2 = #FFFFFF und A1 = 0,92; das berechnete RGB1 = rgb (2, 40, 13), aber rgba (2, 40, 13, 0,92) = # 15381F, nicht # 163920.
30.
12

Ich habe ein WENIGER Mixin mit Phrogz 'Antwort gemacht. Sie geben ein:

  1. wie die Farbe aussehen soll
  2. mit einem bestimmten Alpha
  3. auf einem bestimmten Hintergrund (Standard ist weiß)

Hier ist der Code:

.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);

}

Verwendung wie folgt:

@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);
}

Funktioniert offensichtlich nicht für unmögliche Kombinationen (wie von Phrogz erwähnt), was bedeutet, dass nur ein geringes Maß an Transparenz unterstützt wird. Sehen Sie, wie Sie damit umgehen.

Ephemer
quelle
1
@mixin bg_alpha_calc ($ gewünschte_Farbe, $ gewünschte_alpha, $ Hintergrundfarbe: weiß) {$ r3: rot ($ gewünschte_Farbe); $ g3: grün ($ gewünschte_Farbe); $ b3: blau ($ gewünschte_Farbe); $ r2: rot ($ background_colour); $ g2: grün ($ background_colour); $ b2: blau ($ background_colour); // r1 = (r3 - r2 + r2 * a1) / a1 $ r1: ($ r3 - $ r2 + ($ r2 * $ gewünschtes_alpha)) / $ gewünschtes_alpha; $ g1: ($ g3 - $ g2 + ($ g2 * $ gewünschtes_alpha)) / $ gewünschtes_alpha; $ b1: ($ b3 - $ b2 + ($ b2 * $ gewünschtes_alpha)) / $ gewünschtes_alpha; Hintergrundfarbe: $ gewünschte_Farbe; Hintergrundfarbe: rgba ($ r1, $ g1, $ b1, $ gewünschtes_alpha); }
MetaColin
2
Ich habe ein SCSS-Versionsmixin übernommen und erstellt. Die Demo und den Code finden Sie hier: codepen.io/Grienauer/pen/Grogdx
Grienauer
@Grienauer Ich habe genau das Gleiche getan, habe nicht bemerkt, dass du es bereits geteilt hast! Mein einziger Unterschied ist, dass ich die Hintergrundfarbe
standardmäßig
7

Dank Phrogz 's und ephemer ist toll Antworten, hier ist eine SASS Funktion , dass automatisch die beste äquivalent RGBA Farbe berechnet.

Sie rufen es mit der gewünschten Farbe und dem vorhandenen Hintergrund auf und es berechnet die beste (dh transparenteste) äquivalente RGBA-Farbe, die das gewünschte Ergebnis innerhalb von ± 1/256 jeder RGB-Komponente liefert (aufgrund von Rundungsfehlern):

@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);
}

Ich habe es gerade gegen eine Reihe von Kombinationen getestet (alle Bootswatch-Themen) und es ist ein Vergnügen, sowohl für Dunkel-bei-Licht- als auch für Hell-bei-Dunkel-Ergebnisse.

PS: Wenn Sie eine bessere Genauigkeit als ± 1/256 in der resultierenden Farbe benötigen, müssen Sie wissen, welche Art von Rundungsalgorithmus-Browsern beim Mischen von RGBA-Farben angewendet werden (ich weiß nicht, ob dies standardisiert ist oder nicht), und eine geeignete hinzufügen Bedingung zum Bestehenden @while, so dass es weiter zunimmt, $alphabis es die gewünschte Präzision erreicht.

Tobia
quelle
2
Zu Ihrer Information , diese Funktion existiert in Stylus als transparentify(): stylus-lang.com/docs/bifs.html#transparentifytop-bottom-alpha ... die ich entdeckt habe, nachdem ich sie manuell auf Stylus
portiert habe
6

Aus der Antwort von @Phrogz:

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

So:

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

So:

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

Beachten Sie einen beliebigen Wert von auswählen können a1, und dies wird die entsprechenden Werte finden r1, g1und b1erforderlich. Wenn Sie beispielsweise ein Alpha von 1 auswählen, benötigen Sie RGB1 = RGB3, aber wenn Sie ein Alpha von 0 auswählen, wird (offensichtlich) keine Lösung gefunden.

Eric
quelle
0

Um die Antwort von @ Tobia zu erweitern und die Deckkraft eher wie transparent zu spezifizieren:

@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);
}
Phazei
quelle