it-swarm.com.de

Eine Farbe programmatisch aufhellen

Motivation

Ich möchte einen Weg finden, eine beliebige Farbe zu nehmen und sie ein paar Schattierungen aufzuhellen, damit ich programmatisch einen schönen Farbverlauf von der einen Farbe zu einer helleren Version erstellen kann. Der Verlauf wird als Hintergrund in einer Benutzeroberfläche verwendet.

Möglichkeit 1

Natürlich kann ich die RGB-Werte einfach aufteilen und einzeln um einen bestimmten Betrag erhöhen. Ist das wirklich was ich will?

Möglichkeit 2

Mein zweiter Gedanke war, RGB in HSV/HSB/HSL umzuwandeln (Farbton, Sättigung, Wert/Helligkeit/Helligkeit), die Helligkeit ein wenig zu erhöhen, die Sättigung ein wenig zu verringern und sie dann wieder in RGB umzuwandeln. Wird dies generell den gewünschten Effekt haben?

70
Dave Lockhart

Ich würde mich für die zweite Option entscheiden. Im Allgemeinen eignet sich der RGB-Raum nicht für Farbmanipulationen (Übergang von einer Farbe zu einer anderen, Aufhellen/Abdunkeln einer Farbe usw.). Im Folgenden sind zwei Websites aufgeführt, die ich mit einer Schnellsuche gefunden habe, um von/zu RGB zu/von HSL zu konvertieren:

38
Grey Panther

Wie Wedge said , Sie möchten multiplizieren, um die Dinge heller zu machen, aber das funktioniert nur, bis eine der Farben gesättigt wird (d. H. Treffer 255 oder höher). An diesem Punkt können Sie die Werte einfach auf 255 begrenzen, aber Sie werden den Farbton subtil ändern, wenn Sie heller werden. Um den Farbton beizubehalten, möchten Sie das Verhältnis (Mittel-Tiefst)/(Hoch-Tiefst) beibehalten.

Hier sind zwei Funktionen in Python. Der erste implementiert den naiven Ansatz, bei dem die RGB-Werte nur auf 255 geklemmt werden, wenn sie überschritten werden. Die zweite Komponente verteilt die überschüssigen Werte neu, um den Farbton beizubehalten.

def clamp_rgb(r, g, b):
    return min(255, int(r)), min(255, int(g)), min(255, int(b))

def redistribute_rgb(r, g, b):
    threshold = 255.999
    m = max(r, g, b)
    if m <= threshold:
        return int(r), int(g), int(b)
    total = r + g + b
    if total >= 3 * threshold:
        return int(threshold), int(threshold), int(threshold)
    x = (3 * threshold - total) / (3 * m - total)
    gray = threshold - x * m
    return int(gray + x * r), int(gray + x * g), int(gray + x * b)

Ich habe einen Verlauf erstellt, der mit dem RGB-Wert (224,128,0) begann und diesen mit 1,0, 1,1, 1,2 usw. bis 2,0 multiplizierte. Die obere Hälfte ist das Ergebnis mit clamp_rgb und die untere Hälfte ist das Ergebnis mit redistribute_rgb. Ich denke, es ist leicht zu erkennen, dass die Umverteilung der Überläufe ein viel besseres Ergebnis liefert, ohne den RGB-Farbraum verlassen zu müssen.

Lightness gradient with clamping (top) and redistribution (bottom)

Zum Vergleich ist hier derselbe Farbverlauf im HLS- und HSV-Farbraum, wie er vom Python-Modul colorsys implementiert wurde. Nur die Komponente L wurde geändert, und die resultierenden RGB-Werte wurden geklemmt. Die Ergebnisse sind ähnlich, erfordern jedoch Farbraumkonvertierungen für jedes Pixel.

Lightness gradient with HLS (top) and HSV (bottom)

55
Mark Ransom

In C #:

public static Color Lighten(Color inColor, double inAmount)
{
  return Color.FromArgb(
    inColor.A,
    (int) Math.Min(255, inColor.R + 255 * inAmount),
    (int) Math.Min(255, inColor.G + 255 * inAmount),
    (int) Math.Min(255, inColor.B + 255 * inAmount) );
}

Ich habe das überall benutzt.

23
Nick

Die ControlPaint-Klasse im System.Windows.Forms-Namespace verfügt über statische Methoden Light und Dark:

public static Color Dark(Color baseColor, float percOfDarkDark);

Diese Methoden verwenden die private Implementierung von HLSColor. Ich wünschte, diese Struktur wäre öffentlich und in System.Drawing.

Alternativ können Sie GetHue, GetSaturation, GetBrightness on Color struct verwenden, um HSB-Komponenten abzurufen. Leider habe ich die umgekehrte Konvertierung nicht gefunden.

11
Ilya Ryzhenkov

Konvertieren Sie es in RGB und interpolieren Sie linear zwischen der Originalfarbe und der Zielfarbe (oft weiß). Wenn Sie also 16 Schattierungen zwischen zwei Farben wünschen, tun Sie Folgendes:


for(i = 0; i < 16; i++)
{
  colors[i].R = start.R + (i * (end.R - start.R)) / 15;
  colors[i].G = start.G + (i * (end.G - start.G)) / 15;
  colors[i].B = start.B + (i * (end.B - start.B)) / 15;
}
8
Adam Rosenfield

Um eine hellere oder dunklere Version einer bestimmten Farbe zu erhalten, sollten Sie deren Helligkeit ändern. Sie können dies problemlos tun, auch ohne Ihre Farbe in HSL- oder HSB-Farbe umzuwandeln. Um beispielsweise eine Farbe heller zu machen, können Sie den folgenden Code verwenden:

float correctionFactor = 0.5f;
float red = (255 - color.R) * correctionFactor + color.R;
float green = (255 - color.G) * correctionFactor + color.G;
float blue = (255 - color.B) * correctionFactor + color.B;
Color lighterColor = Color.FromArgb(color.A, (int)red, (int)green, (int)blue);

Wenn Sie weitere Informationen benötigen, lesen Sie den vollständigen Artikel in meinem Blog .

6
Pavel Vladov

Eine sehr ähnliche Frage mit nützlichen Antworten wurde zuvor gestellt: Wie bestimme ich dunklere oder hellere Farbvarianten einer bestimmten Farbe?

Kurze Antwort: Multiplizieren Sie die RGB-Werte mit einer Konstanten, wenn Sie nur "gut genug" benötigen, und übersetzen Sie sie in HSV, wenn Sie Genauigkeit benötigen.

3
Wedge

Ich habe Andrews Antwort und Marks Antwort verwendet, um this (ab 1/2013 keine Bereichseingabe für ff) zu machen.

function calcLightness(l, r, g, b) {
    var tmp_r = r;
    var tmp_g = g;
    var tmp_b = b;

    tmp_r = (255 - r) * l + r;
    tmp_g = (255 - g) * l + g;
    tmp_b = (255 - b) * l + b;

    if (tmp_r > 255 || tmp_g > 255 || tmp_b > 255) 
        return { r: r, g: g, b: b };
    else 
        return { r:parseInt(tmp_r), g:parseInt(tmp_g), b:parseInt(tmp_b) }
}

enter image description here

3
user1873073

Das Konvertieren in HS (LVB), das Erhöhen der Helligkeit und das anschließende Konvertieren in RGB ist die einzige Möglichkeit, die Farbe zuverlässig aufzuhellen, ohne die Farbton- und Sättigungswerte zu beeinflussen (dh die Farbe nur aufzuhellen, ohne sie auf andere Weise zu ändern).

2
David Arno

Ich habe dies in beide Richtungen getan - mit Möglichkeit 2 erzielen Sie viel bessere Ergebnisse.

Jeder einfache Algorithmus, den Sie für Möglichkeit 1 konstruieren, funktioniert wahrscheinlich nur für einen begrenzten Bereich von Startsättigungen.

Sie möchten sich mit Poss 1 befassen, wenn (1) Sie die verwendeten Farben und Helligkeiten einschränken können und (2) Sie die Berechnung häufig in einem Rendering ausführen.

Das Generieren des Hintergrunds für eine Benutzeroberfläche erfordert nicht sehr viele Schattierungsberechnungen, daher schlage ich Poss 2 vor.

-Al.

2
A I Breveleri

Ein bisschen zu spät zur Party, aber wenn Sie javascript oder nodejs verwenden, können Sie tinycolor library verwenden und die Farbe nach Ihren Wünschen bearbeiten:

tinycolor("red").lighten().desaturate().toHexString() // "#f53d3d" 
1
Ari

Ich habe diese Frage erst gefunden, nachdem sie mit meiner ursprünglichen Frage verwandt war.

Verwenden Sie jedoch die Erkenntnisse aus diesen tollen Antworten. Dazu habe ich eine Nice-Two-Liner-Funktion zusammengestellt:

Hex-Farben (oder RGB-Farben und Mischfarben) programmatisch aufhellen oder abdunkeln

Es ist eine Version von Methode 1. Aber mit übermäßiger Sättigung berücksichtigt. Wie Keith in seiner Antwort oben sagte; Verwenden Sie Lerp, um anscheinend dasselbe Problem wie Mark zu lösen, jedoch ohne Umverteilung. Die ergebnisse von shadeColor2 sollte viel näher dran sein, es mit HSL richtig zu machen, aber ohne Overhead.

1
Pimp Trizkit

Methode 1: Konvertieren Sie RGB in HSL, passen Sie HSL an, konvertieren Sie zurück in RGB.

Methode 2: Lerp die RGB-Farbwerte - http://en.wikipedia.org/wiki/Lerp_ (computing)

Siehe meine Antwort auf diese ähnliche Frage für eine C # -Implementierung von Methode 2.

1
Keith

Stellen Sie sich vor, Sie hätten Alpha zu Weiß gemischt:

oneMinus = 1.0 - amount
r = amount + oneMinus * r
g = amount + oneMinus * g
b = amount + oneMinus * b

dabei ist amount von 0 bis 1, wobei 0 die ursprüngliche Farbe und 1 Weiß zurückgibt.

Möglicherweise möchten Sie die Hintergrundfarbe anpassen, wenn Sie aufhellen, um etwas Deaktiviertes anzuzeigen:

oneMinus = 1.0 - amount
r = amount * dest_r + oneMinus * r
g = amount * dest_g + oneMinus * g
b = amount * dest_b + oneMinus * b

wo (dest_r, dest_g, dest_b) ist die Farbe, mit der gemischt wird, und amount ist von 0 bis 1, wobei Null zurückgibt (r, g, b) und 1 zurück (dest.r, dest.g, dest.b)

1
prewett

WENN Sie ein Farbverlaufs-Ausblenden erzeugen möchten, würde ich die folgende Optimierung vorschlagen: Anstatt RGB-> HSB-> RGB für jede einzelne Farbe auszuführen, sollten Sie nur die Zielfarbe berechnen. Sobald Sie das Ziel-RGB kennen, können Sie einfach die Zwischenwerte im RGB-Raum berechnen, ohne sie vor und zurück konvertieren zu müssen. Ob Sie einen linearen Nutzungsübergang oder eine Kurve berechnen, bleibt Ihnen überlassen.

1
VoidPointer

Ich hätte zuerst Nummer 1 ausprobiert, aber Nummer 2 klingt ziemlich gut. Versuchen Sie es selbst und sehen Sie, ob Sie mit den Ergebnissen zufrieden sind. Es hört sich so an, als würden Sie vielleicht 10 Minuten brauchen, um einen Test zu erstellen.

0
davr

Technisch halte ich auch nichts für richtig, aber ich glaube, Sie möchten eine Variante von Option 2. Das Problem ist, dass RGB 990000 und "Aufhellen" nur zum roten Kanal (Wert, Helligkeit, Helligkeit) addiert wird, bis Sie zu FF gelangen. Danach (durchgehend rot) würde es die Sättigung verringern, um vollständig zu durchgehend weiß zu gelangen.

Die Konvertierungen werden ärgerlich, zumal Sie nicht direkt zu RGB und Lab wechseln können, aber ich denke, Sie möchten die Chrominanz- und Luminanzwerte wirklich trennen und nur die Luminanz ändern, um wirklich das zu erreichen, was Sie wollen.

0

Hier ist ein Beispiel für das Aufhellen einer RGB-Farbe in Python:

def lighten(hex, amount):
    """ Lighten an RGB color by an amount (between 0 and 1),

    e.g. lighten('#4290e5', .5) = #C1FFFF
    """
    hex = hex.replace('#','')
    red = min(255, int(hex[0:2], 16) + 255 * amount)
    green = min(255, int(hex[2:4], 16) + 255 * amount)
    blue = min(255, int(hex[4:6], 16) + 255 * amount)
    return "#%X%X%X" % (int(red), int(green), int(blue))
0
Aidan

Ich habe ein Blogpost , das zeigt, wie das in Delphi gemacht wird. Es ist ziemlich einfach, da die Funktionen ColorRGBToHSL und ColorHLSToRGB Teil der Standardbibliothek sind.

0

Code zum Konvertieren zwischen Farbräumen finden Sie in der color-tools Ruby library

0