how to get the opposite color of any background images
-
09-10-2019 - |
Question
how to get the right color automatically that is depending on the background? if its darker background image, that will automatically change the font color into brighter colors. was it possible? any idea?
Solution
David's answer is generally working very well. But there are a few options, and I will mention some of them. First, the very most naïve approach, is to do
function InvertColor(const Color: TColor): TColor;
begin
result := TColor(Windows.RGB(255 - GetRValue(Color),
255 - GetGValue(Color),
255 - GetBValue(Color)));
end;
but this suffers from the #808080 problem (why?). A very nice solution is David's, but it looks very bad for some unfortunate background colours. Although the text is certainly visible, it looks horrible. One such "unfortunate" background colour is #008080.
Usually I prefer the text to be black if the background is "light", and white if the background is "dark". I thus do
function InvertColor(const Color: TColor): TColor;
begin
if (GetRValue(Color) + GetGValue(Color) + GetBValue(Color)) > 384 then
result := clBlack
else
result := clWhite;
end;
Also, if you are using Delphi 2009+ and targeting Windows Vista+, you might be interested in the GlowSize
parameter of the TLabel
.
OTHER TIPS
I use the following to give me a color that contrasts the specified color:
function xorColor(BackgroundColor: TColor): TColor;
begin
BackgroundColor := ColorToRGB(BackgroundColor);
Result := RGB(
IfThen(GetRValue(BackgroundColor)>$40, $00, $FF),
IfThen(GetGValue(BackgroundColor)>$40, $00, $FF),
IfThen(GetBValue(BackgroundColor)>$40, $00, $FF)
);
end;
I try compute contrast based on "linear" color scheme, but it is really not good on pink and cyan color input values. Much better it is calculate based on RGB formula:
brightness = sqrt( .241 * R^2 + .691 * G^2 + .068 * B^2 )
In Delphi i create this subroutine:
function GetContrastingColor(Color: TColor): TColor;
var r,g,b:double;i:integer;
begin
Color := ColorToRGB(Color);
r:=GetRValue(Color) ;
g:=GetGValue(Color) ;
b:=GetBValue(Color) ;
i:=round( Sqrt(
r * r * 0.241 +
g * g * 0.691 +
b * b * 0.068));
if (i > 128) then // treshold seems good in wide range
Result := clBlack
else
Result := clWhite;
end;
I had issues with D6, when the TColor
was clWindow
. I discovered that if I did not first run ColorToRGB(Color)
, GetXValue(Color)
would report the R,G,B value of clWindow
as 5,0,0 respectively. Which is nearly black, while clWindow
was defined as 255,255,255 on my test environment. This seems to only be a problem for values sent in using the constant, if I sent in the hex or int equivalents it worked fine.
function InvertColor(const Color: TColor): TColor;
begin
if (GetRValue(ColorToRGB(Color)) +
GetGValue(ColorToRGB(Color)) +
GetBValue(ColorToRGB(Color)))/3 > 128 then
result := clBlack //color is light
else
result := clWhite; //color is dark
end;