Zrób foregroundcolor czarny lub biały w zależności od tła

Coś jak obliczanie średniej wartości komponentów rgb, a następnie zdecydować, czy użyć czerni czy bieli?

Czy muszę przekonwertować RGB na HSV w pierwszym kroku, ponieważ RGB nie zawsze jest tym, co widzą ludzkie oczy?

Używam C #

 31
Author: Kai, 2010-02-11

5 answers

Tak się składa, że nie tak dawno potrzebowałem tej funkcji w projekcie.

private int PerceivedBrightness(Color c)
{
    return (int)Math.Sqrt(
    c.R * c.R * .241 +
    c.G * c.G * .691 +
    c.B * c.B * .068);
}

Tę formułę znalazłem w Internecie na NBD Tech , która zajmowała się postrzeganymi kolorami i formułą konwersji kolorów. Strona daje wiele informacji, które są pomocne.

Oto jak użyć tego, aby wybrać czarny lub biały:

var foreColor = (PerceivedBrightness(backColor) > 130 ? Color.Black : Color.White);

Możesz użyć wartości innej niż 130 jako odcięcia; jest to preferencja.


Update: według Darel Rex Finley na jego miejsce :

Wartości, które wymyśliłem bawiąc się Photoshopem, były w rzeczywistości .241, .691, oraz068, ale od tego czasu zostałem poinformowany, że wartości .299, .587, oraz114 są dokładniejsze.

Niniejsza specyfikacja jest zgodna z zaleceniem ITU-R BT.601 (lub Rec. 601 W skrócie). Strona, o której wspomniałem powyżej, NBD Tech , nie została jeszcze zaktualizowana, aby to odzwierciedlić.

W oparciu o to, oto zaktualizowana metoda (Dzięki DTI-Matt za komentarz):

private int PerceivedBrightness(Color c)
{
    return (int)Math.Sqrt(
    c.R * c.R * .299 +
    c.G * c.G * .587 +
    c.B * c.B * .114);
}

Uwaga dotycząca preferencji progu:

[[3]}kolory z postrzeganą jasnością blisko środka (np. 120-140) będą bardziej subiektywne. Na przykład dyskusyjne jest to, czy czerwony (FF0000), który ocenia się na 139, jest wyraźniejszy z czarną lub białą nakładką.

Biało-czarny na czerwonym

 61
Author: JYelton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-20 20:37:42

Co ty na to?

private static Color GetReadableForeColor(Color c)
{
    return (((c.R + c.B + c.G) / 3) > 128) ? Color.Black : Color.White;
}
 5
Author: Kai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-11 01:15:07

Struktura Color wspiera konwersję do HSB natywnie.

if (Color.GetBrightness() > 0.5f) {
  // win
}

Możesz również dodać składnik nasycenia, biorąc pod uwagę, że nasycenie przyczynia się również do pozornej "lekkości".

 4
Author: Ron Warholic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-25 16:20:50

Możesz wykonać proste obliczenia w zależności od głębi kolorów, jeśli powiedzmy, że masz format kolorów #FFFFFF, możesz po prostu dodać wartości RGB i obliczyć, czy są w połowie drogi.

Max w tym przypadku wynosi 255 (F x F = 256) NA, więc po prostu sprawdź, czy jest poniżej tego progu:

var colorCode = ((R + B + G) < 255*3) ? "#FFFFFF" : "#000000";
Jeśli kolor jest poniżej, jest ciemniejszy...użyj białego tła. Jeśli jest na górze, jest lżejszy...użyj czarnego tła. To nie jest idealne, ale pomysł na początek.
 0
Author: Nick Craver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-11 00:41:43

Jeśli dobrze rozumiem, jednym z sposobów może być zdobycie obrazu tapety na pulpit, sprawdzenie w jakimś manor jaki jest kolor i następnie zmiana koloru aplikacji na podstawie tego.

Jest Artykuł na geekpedia o zdobyciu aktualnej tapety na pulpit( i wielu odsłon w google na tym), ale podstawowym założeniem jest chwycenie wartości rejestru bieżącej tapety:

RegistryKey rkWallPaper = Registry.CurrentUser.OpenSubKey("Control Panel\\Desktop", false);
string WallpaperPath = rkWallPaper.GetValue("WallPaper").ToString();

Możesz użyć tej ścieżki, aby otworzyć obraz. Możesz wtedy uzyskaj wiele właściwości, takich jak wymiary i pojedyncze kolory pikseli W RGB.

Aby dowiedzieć się, czy jest "więcej bieli" czy "więcej czerni", masz wiele opcji.

Jednym z pomysłów byłoby uzyskanie koloru każdego piksela W RGB, uśrednianie wartości (aby uzyskać wartość w skali szarości), a następnie uśrednianie wartości w skali szarości każdego piksela na obrazie. Jeśli to wyjdzie > 128, to Może być "biały". If

// Psudo code - can't check the C# spec atm.
foreach(Pixel p in image)
{
    // get average of colour components.
    double greyScale = (p.Red + p.Green + p.Blue) / 3;
    totalIntensity += greyScale;
}

double averageImageIntensity = totalIntensity / image.NumPixels;

if(totalIntensity > 128) // image could be considered to be "white"
else // image could be considered "black".

Problemy: może to być powolna procedura, możesz chcieć samplować tylko niektóre piksele (powiedzmy, co dziesiąty itp.), aby zaoszczędzić czas. Ogólnie rzecz biorąc, wydaje się to dość trudne do zrobienia w ogóle. Pobieranie plików użytkownika w czasie wykonywania i mieszanie z nimi nie jest łatwe, a to zapewnia potencjalne problemy z bezpieczeństwem i stabilnością. Co jeśli obraz jest duff lub uszkodzony itp.

Osobiście sugerowałbym po prostu dając użytkownikowi wybór koloru / motywu / skórki, albo jeszcze lepiej pozwól mu ją dostosować!

 -1
Author: xan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-02-11 00:51:53