Ermitteln Sie die Schriftfarbe anhand der Hintergrundfarbe

Bei einem System (z. B. einer Website), bei dem ein Benutzer die Hintergrundfarbe für einen Abschnitt, nicht aber die Schriftfarbe anpassen kann (um die Anzahl der Optionen auf ein Minimum zu beschränken), gibt es eine Möglichkeit, programmgesteuert zu bestimmen, ob ein “Licht” oder ” dunkel “Schriftfarbe ist notwendig?

Ich bin mir sicher, dass es einen Algorithmus gibt, aber ich weiß nicht genug über colors, Leuchtkraft usw., um es selbst herauszufinden.

Ich stieß auf ein ähnliches Problem. Ich musste eine gute Methode finden, kontrastive Schriftfarbe auszuwählen, um Textbeschriftungen auf Farbskalen / Heatmaps anzuzeigen. Es musste eine universelle Methode sein und die generierte Farbe musste “gutaussehend” sein, was bedeutet, dass die einfache Erzeugung komplementärer colors keine gute Lösung war – manchmal erzeugte sie seltsame, sehr intensive colors, die schwer zu sehen und zu lesen waren.

Nach langen Teststunden und Versuchen, dieses Problem zu lösen, fand ich heraus, dass die beste Lösung darin besteht, weiße Schrift für “dunkle” colors und schwarze Schrift für “helle” colors auszuwählen.

Hier ist ein Beispiel für die function, die ich in C # verwende:

Color ContrastColor(Color color) { int d = 0; // Counting the perceptive luminance - human eye favors green color... double luminance = ( 0.299 * color.R + 0.587 * color.G + 0.114 * color.B)/255; if (luminance > 0.5) d = 0; // bright colors - black font else d = 255; // dark colors - white font return Color.FromArgb(d, d, d); } 

Dies wurde für viele verschiedene Farbskalen (Regenbogen, Graustufen, Hitze, Eis und viele andere) getestet und ist die einzige “universelle” Methode, die ich herausgefunden habe.

Bearbeiten
Die Formel des Zählens von a in “perceptive luminance” geändert – es sieht wirklich besser aus! Bereits in meiner Software implementiert, sieht gut aus.

Edit 2 @WebSeed bot ein großartiges Arbeitsbeispiel für diesen Algorithmus: http://codepen.io/WebSeed/full/pvgqEq/

Danke @Gacek . Hier ist eine Version für Android:

 @ColorInt public static int getContrastColor(@ColorInt int color) { // Counting the perceptive luminance - human eye favors green color... double a = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255; int d; if (a < 0.5) { d = 0; // bright colors - black font } else { d = 255; // dark colors - white font } return Color.rgb(d, d, d); } 

Und eine verbesserte (kürzere) Version:

 @ColorInt public static int getContrastColor(@ColorInt int color) { // Counting the perceptive luminance - human eye favors green color... double a = 1 - (0.299 * Color.red(color) + 0.587 * Color.green(color) + 0.114 * Color.blue(color)) / 255; return a < 0.5 ? Color.BLACK : Color.WHITE; } 

Für den Fall, dass jemand eine kürzere, vielleicht besser verständliche Version von GaceKs Antwort möchte :

 public Color ContrastColor(Color iColor) { // Calculate the perceptive luminance (aka luma) - human eye favors green color... double luma = ((0.299 * iColor.R) + (0.587 * iColor.G) + (0.114 * iColor.B)) / 255; // Return black for bright colors, white for dark colors return luma > 0.5 ? Color.Black : Color.White; } 

Hinweis: Ich habe die Inversion des Luma- Wertes entfernt (damit helle colors einen höheren Wert haben, was mir natürlicher erscheint und auch die ‘Standard’-Berechnungsmethode ist).

Ich habe die gleichen Konstanten wie GaceK von hier verwendet, da sie großartig für mich funktionierten.

(Sie können dies auch als Extension-Methode implementieren, indem Sie die folgende Signatur verwenden:

 public static Color ContrastColor(this Color iColor) 

Sie können es dann über foregroundColor = background.ContrastColor() aufrufen.)

Meine schnelle Umsetzung von Gaceks Antwort:

 func contrastColor(color: UIColor) -> UIColor { var d = CGFloat(0) var r = CGFloat(0) var g = CGFloat(0) var b = CGFloat(0) var a = CGFloat(0) color.getRed(&r, green: &g, blue: &b, alpha: &a) // Counting the perceptive luminance - human eye favors green color... let luminance = 1 - ((0.299 * r) + (0.587 * g) + (0.114 * b)) if luminance < 0.5 { d = CGFloat(0) // bright colors - black font } else { d = CGFloat(1) // dark colors - white font } return UIColor( red: d, green: d, blue: d, alpha: a) } 

Javascript [ES2015]

 const hexToLuma = (colour) => { const hex = colour.replace(/#/, ''); const r = parseInt(hex.substr(0, 2), 16); const g = parseInt(hex.substr(2, 2), 16); const b = parseInt(hex.substr(4, 2), 16); return [ 0.299 * r, 0.587 * g, 0.114 * b ].reduce((a, b) => a + b) / 255; }; 

Das ist so eine hilfreiche Antwort. Danke dafür!

Ich möchte eine SCSS-Version teilen:

 @function is-color-light( $color ) { // Get the components of the specified color $red: red( $color ); $green: green( $color ); $blue: blue( $color ); // Compute the perceptive luminance, keeping // in mind that the human eye favors green. $l: 1 - ( 0.299 * $red + 0.587 * $green + 0.114 * $blue ) / 255; @return ( $l < 0.5 ); } 

Jetzt erfahren Sie, wie Sie mit dem Algorithmus Hover-colors für Menüverknüpfungen automatisch erstellen. Helle Header erhalten einen dunkleren Hover und umgekehrt.

Danke für diesen Beitrag.

Für wen auch immer interessiert, hier ist ein Beispiel für diese function in Delphi:

 function GetContrastColor(ABGColor: TColor): TColor; var ADouble: Double; R, G, B: Byte; begin if ABGColor < = 0 then begin Result := clWhite; Exit; // *** EXIT RIGHT HERE *** end; if ABGColor = clWhite then begin Result := clBlack; Exit; // *** EXIT RIGHT HERE *** end; // Get RGB from Color R := GetRValue(ABGColor); G := GetGValue(ABGColor); B := GetBValue(ABGColor); // Counting the perceptive luminance - human eye favors green color... ADouble := 1 - (0.299 * R + 0.587 * G + 0.114 * B) / 255; if (ADouble < 0.5) then Result := clBlack; // bright colors - black font else Result := clWhite; // dark colors - white font end; 

Hässliche Python, wenn Sie nicht Lust haben, es zu schreiben 🙂

 ''' Input a string without hash sign of RGB hex digits to compute complementary contrasting color such as for fonts ''' def contrasting_text_color(hex_str): (r, g, b) = (hex_str[:2], hex_str[2:4], hex_str[4:]) return '000' if 1 - (int(r, 16) * 0.299 + int(g, 16) * 0.587 + int(b, 16) * 0.114) / 255 < 0.5 else 'fff' 

Ich hatte das gleiche Problem, aber ich musste es in PHP entwickeln . Ich habe @ Gareks Lösung verwendet und diese Antwort auch verwendet: Konvertiere Hex-Farbe in RGB-Werte in PHP , um HEX-Farbcode in RGB umzuwandeln.

Also ich teile es.

Ich wollte diese function mit der angegebenen Hintergrund-HEX-Farbe verwenden, aber nicht immer mit ‘#’ beginnen.

 //So it can be used like this way: $color = calculateColor('#804040'); echo $color; //or even this way: $color = calculateColor('D79C44'); echo '
'.$color; function calculateColor($bgColor){ //ensure that the color code will not have # in the beginning $bgColor = str_replace('#','',$bgColor); //now just add it $hex = '#'.$bgColor; list($r, $g, $b) = sscanf($hex, "#%02x%02x%02x"); $color = 1 - ( 0.299 * $r + 0.587 * $g + 0.114 * $b)/255; if ($color < 0.5) $color = '#000000'; // bright colors - black font else $color = '#ffffff'; // dark colors - white font return $color; }

iOS Swift 3.0 (UIColor Erweiterung):

 func isLight() -> Bool { if let components = self.cgColor.components, let firstComponentValue = components[0], let secondComponentValue = components[1], let thirdComponentValue = components[2] { let firstComponent = (firstComponentValue * 299) let secondComponent = (secondComponentValue * 587) let thirdComponent = (thirdComponentValue * 114) let brightness = (firstComponent + secondComponent + thirdComponent) / 1000 if brightness < 0.5 { return false }else{ return true } } print("Unable to grab components and determine brightness") return nil } 

Wenn Sie Farbräume für visuelle Effekte manipulieren, ist es in der Regel einfacher, in HSL (Farbton, Sättigung und Helligkeit) als RGB zu arbeiten. colors in RGB zu bewegen, um natürlich angenehme Effekte zu erzielen, ist in der Regel konzeptionell schwierig, während das Umwandeln in HSL, das Manipulieren dort und das anschließende Zurückkonvertieren intuitiver ist und immer bessere Ergebnisse liefert.

Wikipedia hat eine gute Einführung in HSL und den eng verwandten HSV. Und es gibt kostenlosen Code im Netz, um die Konvertierung durchzuführen ( hier ist beispielsweise eine Javascript-Implementierung )

Welche präzise Transformation Sie verwenden, ist Geschmackssache, aber persönlich hätte ich gedacht, dass die Umkehrung der Hue- und Lightness-Komponenten sicher eine gute kontrastreiche Farbe als erste Annäherung erzeugen würde, aber Sie können leicht subtilere Effekte erzielen.

Sie können jeden Farbton-Text auf jedem Farbton-Hintergrund haben und sicherstellen, dass er lesbar ist. Das mache ich die ganze Zeit. Es gibt eine Formel dafür in Javascript auf lesbarem Text in Farbe – STW * Wie es auf diesem Link sagt, ist die Formel eine Variation der Inverse-Gamma-Anpassung Berechnung, obwohl ein bisschen mehr überschaubar IMHO. Die Menüs auf der rechten Seite dieses Links und die zugehörigen Seiten verwenden zufällig generierte colors für Text und Hintergrund, immer lesbar. Also ja, klar kann es gemacht werden, kein Problem.

Als Kotlin / Android Erweiterung:

 fun Int.getContrastColor(): Int { // Counting the perceptive luminance - human eye favors green color... val a = 1 - (0.299 * Color.red(this) + 0.587 * Color.green(this) + 0.114 * Color.blue(this)) / 255 return if (a < 0.5) Color.BLACK else Color.WHITE } 

Eine Android-Variante, die auch das Alpha erfasst.

(Danke @ Thomas-Vos)

 /** * Returns a colour best suited to contrast with the input colour. * * @param colour * @return */ @ColorInt public static int contrastingColour(@ColorInt int colour) { // XXX https://stackoverflow.com/questions/1855884/determine-font-color-based-on-background-color // Counting the perceptive luminance - human eye favors green color... double a = 1 - (0.299 * Color.red(colour) + 0.587 * Color.green(colour) + 0.114 * Color.blue(colour)) / 255; int alpha = Color.alpha(colour); int d = 0; // bright colours - black font; if (a >= 0.5) { d = 255; // dark colours - white font } return Color.argb(alpha, d, d, d); } 

Eine Implementierung für das Ziel-c

 + (UIColor*) getContrastColor:(UIColor*) color { CGFloat red, green, blue, alpha; [color getRed:&red green:&green blue:&blue alpha:&alpha]; double a = ( 0.299 * red + 0.587 * green + 0.114 * blue); return (a > 0.5) ? [[UIColor alloc]initWithRed:0 green:0 blue:0 alpha:1] : [[UIColor alloc]initWithRed:255 green:255 blue:255 alpha:1]; } 

Schnell 4 Beispiel:

 extension UIColor { var isLight: Bool { let components = cgColor.components let firstComponent = ((components?[0]) ?? 0) * 299 let secondComponent = ((components?[1]) ?? 0) * 587 let thirdComponent = ((components?[2]) ?? 0) * 114 let brightness = (firstComponent + secondComponent + thirdComponent) / 1000 return !(brightness < 0.6) } } 

UPDATE - Gefunden, dass 0.6 ein besseres Testbett für die Abfrage war