2005. április 3., vasárnap
Convert between RGB and HSB color spaces and back
Problem/Question/Abstract:
Is there any way to convert a set of colors that look good on a random background, and have them look "complimentary" and have good contrast with the background? What I have is a chart with an arbitrary background color. What I want to do is to automatically come up with a set of colors for channels that will look good on that arbitarary background color.
Answer:
I found some C++ functions to convert between RGB and HSB, and converted them to Pascal (hopefully correctly):
procedure TForm1.RGBtoHSB(const r, g, b: Integer; var h, s, br: Double);
var
largestColor: Integer; {holds the largest color (RGB) at the start}
lowestColor: Integer; {opposite of above}
hue: Double; {it puts the "H" in "HSB"}
saturation: Double; {S}
brightness: Double; {and the B}
redRatio: Double;
greenRatio: Double;
blueRatio: Double;
begin
{assign largestColor to the greater of the red or green}
if (r <= g) then
largestColor := g
else
largestColor := r;
{now see if blue is bigger}
if (b > largestColor) then
largestColor := b;
{set lowestColor = to the smallest value}
if (g < r) then
lowestColor := g
else
lowestColor := r;
if (b < lowestColor) then
lowestColor := b;
{brightness is calculated like so:}
brightness := largestColor / 255.0;
{if the largestColor isn't zero (so we don't divide by zero) set the variable to
the difference of the two as a percentage of the largest}
if (largestColor <> 0) then
saturation := (largestColor - lowestColor) / largestColor
else
saturation := 0.0;
if (saturation = 0.0) then
hue := 0.0
else
begin
{some temporary variables to figure out the hue}
redRatio := (largestColor - r) / (largestColor - lowestColor);
greenRatio := (largestColor - g) / (largestColor - lowestColor);
blueRatio := (largestColor - b) / (largestColor - lowestColor);
{depending on which of the 3 was the highest, we calculate our hue}
if (r = largestColor) then
hue := blueRatio - greenRatio
else if (g = largestColor) then
hue := (2.0 + redRatio) - blueRatio
else {blue is largest}
hue := (4.0 + greenRatio) - redRatio;
{divide it by 6}
hue := hue / 6.0;
{I don't know if this prevents us from being negative
(as in theworst outcome from the above operations is -1, or if this does
something different)
if (hue < 0.0) then
hue := hue + 1;
end;
{pass back values}
h := hue;
s := saturation;
br := brightness;
end;
procedure TForm1.HSBtoRGB(const hue, saturation, brightness: Double; var r, g, b:
Integer);
const
max = 255;
var
h: Double;
f: Double;
p: Double;
q: Double;
t: Double;
begin
if (saturation = 0) then
begin
r := trunc(brightness * 255);
g := trunc(brightness * 255);
b := trunc(brightness * 255);
end
else
begin
h := (hue - floor(hue)) * 6.0;
f := h - floor(h);
p := brightness * (1.0 - saturation);
q := brightness * (1.0 - saturation * f);
t := brightness * (1.0 - (saturation * (1.0 - f)));
case trunc(h) of
0:
begin
r := trunc(brightness * 255);
g := trunc(t * max);
b := trunc(p * max);
end;
1:
begin
r := trunc(q * max);
g := trunc(brightness * max);
b := trunc(p * max);
end;
2:
begin
r := trunc(p * max);
g := trunc(brightness * max);
b := trunc(t * max);
end;
3:
begin
r := trunc(p * max);
g := trunc(q * max);
b := trunc(brightness * max);
end;
4:
begin
r := trunc(t * max);
g := trunc(p * max);
b := trunc(brightness * max);
end;
5:
begin
r := trunc(brightness * max);
g := trunc(p * max);
b := trunc(q * max);
end;
end;
end;
end;
I then convert each color and the background to HSB, add the Hues of both colors, and then convert the color back to RGB. It works most of the time, but generally the brightness of some of the colors are too bright when the background is too bright, or too dark when the background is too dark.
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése