# RGB to HVS?

Hi!

I would like to create a routine that converts RGB to HVS colors...
(Needed to immitate the disabled menu-items)

Does somebody know how can can derive Hue, Saturation and Value from Red, Green and Blue??

LVL 2
###### Who is Participating?

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Commented:
From http://www.efg2.com/Lab/Graphics/Colors/HSV.htm:

USES
Math,        // MaxValue
IEEE754,  // NaN, IsNaN
SysUtils;    // Exception

TYPE
EColorError = CLASS(Exception);
TReal = DOUBLE;
...
// RGB, each 0 to 255, to HSV.
// H = 0.0 to 360.0 (corresponding to 0..360.0 degrees around hexcone)
// S = 0.0 (shade of gray) to 1.0 (pure color)
// V = 0.0 (black) to 1.0 {white)

// Based on C Code in "Computer Graphics -- Principles and Practice,"
// Foley et al, 1996, p. 592.

PROCEDURE RGBToHSV (CONST R,G,B: TReal; VAR H,S,V: TReal);
VAR
Delta: TReal;
Min : TReal;
BEGIN
Min := MinValue( [R, G, B] );    // USES Math
V := MaxValue( [R, G, B] );

Delta := V - Min;

// Calculate saturation: saturation is 0 if r, g and b are all 0
IF       V = 0.0
THEN S := 0
ELSE S := Delta / V;

IF       S = 0.0
THEN H := NaN    // Achromatic: When s = 0, h is undefined
ELSE BEGIN       // Chromatic
IF       R = V
THEN // between yellow and magenta [degrees]
H := 60.0 * (G - B) / Delta
ELSE
IF       G = V
THEN // between cyan and yellow
H := 120.0 + 60.0 * (B - R) / Delta
ELSE
IF       B = V
THEN // between magenta and cyan
H := 240.0 + 60.0 * (R - G) / Delta;

IF H < 0.0
THEN H := H + 360.0
END
END {RGBtoHSV};

HSVtoRGB

// Based on C Code in "Computer Graphics -- Principles and Practice,"
// Foley et al, 1996, p. 593.
//
// H = 0.0 to 360.0 (corresponding to 0..360 degrees around hexcone)
// NaN (undefined) for S = 0
// S = 0.0 (shade of gray) to 1.0 (pure color)
// V = 0.0 (black) to 1.0 (white)

PROCEDURE HSVtoRGB (CONST H,S,V: TReal; VAR R,G,B: TReal);
VAR
f : TReal;
i : INTEGER;
hTemp: TReal; // since H is CONST parameter
p,q,t: TReal;
BEGIN
IF       S = 0.0    // color is on black-and-white center line
THEN BEGIN
IF       IsNaN(H)
THEN BEGIN
R := V;           // achromatic: shades of gray
G := V;
B := V
END
ELSE RAISE EColorError.Create('HSVtoRGB: S = 0 and H has a value');
END

ELSE BEGIN // chromatic color
IF       H = 360.0         // 360 degrees same as 0 degrees
THEN hTemp := 0.0
ELSE hTemp := H;

hTemp := hTemp / 60;     // h is now IN [0,6)
i := TRUNC(hTemp);        // largest integer <= h
f := hTemp - i;                  // fractional part of h

p := V * (1.0 - S);
q := V * (1.0 - (S * f));
t := V * (1.0 - (S * (1.0 - f)));

CASE i OF
0: BEGIN R := V; G := t;  B := p  END;
1: BEGIN R := q; G := V; B := p  END;
2: BEGIN R := p; G := V; B := t   END;
3: BEGIN R := p; G := q; B := V  END;
4: BEGIN R := t;  G := p; B := V  END;
5: BEGIN R := V; G := p; B := q  END
END
END
END {HSVtoRGB};

Experts Exchange Solution brought to you by

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Author Commented:
Thanks!

But it seems that there are some problems...

I think you know the MSPaint application. But if I use the HSV values from MSPaint as parameters i don't get the correct RGB values from MSPaint!

Do you know how to get the right values?
Commented:
// H = 0.0 to 360.0 (corresponding to 0..360.0 degrees around hexcone)
// S = 0.0 (shade of gray) to 1.0 (pure color)
// V = 0.0 (black) to 1.0 {white)

Perhaps you need to do a correction to values in the rang 0..255 ??

I don't have paint installed, but Paint Shop Pro colors and the output of the HSV tool from http://www.efg2.com/Lab/Graphics/Colors/HSV.htm seem to match.
There is also an integer version of above functions, in HSVLibrary.pas in the .zip file you can download at that site.
Commented:
The comments here might prove enlightening:

http://oldlook.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_10023634.html

Regards,
Steven
Commented:
Hi ChristopH1987,

If you need just fainted image do this way. On the form below just 2 Images, 1 button and 2 Trackbars to adjust Gamma and Intensity. Once you slide TrackBars the Output Image2 will show desaturated bleached copy of the original Image1. Note: example below works with 24 bit bitmaps only.

Ask for details or email for complete project
regards,
<odissey1>

unit DisableImage_1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ComCtrls, ExtCtrls, jpeg, GIFImage,
Math;

type
TForm1 = class(TForm)
Image1: TImage;
TrackBar1: TTrackBar;
Button1: TButton;
Image2: TImage;
TrackBar2: TTrackBar;
procedure Button1Click(Sender: TObject);
procedure TrackBar1Change(Sender: TObject);
procedure TrackBar2Change(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

var
Form1: TForm1;
Gamma: double = 0.5;
Scale: integer = 255;

implementation

{\$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
CONST
PixelCountMax = 32768;
TYPE
pRGBTripleArray = ^TRGBTripleArray;
TRGBTripleArray = ARRAY[0..PixelCountMax-1] OF TRGBTriple;
var
i, j, BitWidth, BitHeigt : integer;
Bitmap1, Bitmap2 : TBitmap;
Row1, Row2:  pRGBTripleArray;
k : integer;
Clr: TRGBTriple;
V: double;
begin
if Color = 0 then result := 0 //don't want 0^x = 1 for x <> 0
else result := round(Scale{255} * Power(Color/255, Gamma) );
end;

begin

Bitmap1 := Image1.Picture.Bitmap;
Bitmap2 := TBitmap.create;
try
Bitmap2.PixelFormat := pf24bit; //always first!
Bitmap2.height := Bitmap1.Height;
Bitmap2.Width  := Bitmap1.Width;
Form1.Caption:='W:'+IntTostr(Bitmap2.Width)+' H:'+IntTostr(Bitmap2.Height);

for i := 0 to (Bitmap2.Height - 1)  do begin
Row1 := Bitmap1.ScanLine[i];
Row2 := Bitmap2.ScanLine[i];
for j := 0 to (Bitmap2.Width - 1) do begin
//              Clr  :=Row1^[j];
//              Clr.rgbtRed  :=Row1^[j].rgbtRed;
//              Clr.rgbtGreen:=Row1^[j].rgbtGreen;
//              Clr.rgbtBlue :=Row1^[j].rgbtBlue;

V:=0.299*Row1^[j].rgbtRed+0.587*Row1^[j].rgbtGreen+0.114*Row1^[j].rgbtBlue;
//              k:=round(V);
Clr.rgbtRed  :=k;
Clr.rgbtGreen:=k;
Clr.rgbtBlue :=k;

Row2[j] := Clr;
end;
end;
Image2.Picture.Graphic :=Bitmap2;

finally
Form1.Caption:='W:'+IntTostr(Bitmap2.Width)+' H:'+IntTostr(Bitmap2.Height);
Bitmap2.free;
end;

end;

procedure TForm1.TrackBar1Change(Sender: TObject);
begin
Gamma:=0.01* TrackBar1.Position;
Button1Click(Self);
end;

procedure TForm1.TrackBar2Change(Sender: TObject);
begin
Scale:=TrackBar2.Position;
Button1Click(Self);

end;

end.
Commented:
Hi ChristopH1987,

any success?

regards,
odissey1
Commented:

:(
Author Commented:
Hey!

Sorry guys...      I had problems with Internet and my Linux...

Thanks for you solutions... They seem to work well, but does somebody know how I can convert RGB to TColor?

PS: I need that to use my Delphi 6 code for Kylix 3. Its the only Win-API that I used but know i need it in Linux 9!

PS: After this question i will split the points ;) ( But i don't like to open a new Question for this and you seem to be fit in Colors :O )
Author Commented:
Odissey1 : Thanks for your complete solution, but I found an easier way to make this (you will get points of course)!
( You derive the brightness of a RGB value and then you set with this brightness a new blue color for this pixel
[its a little more complex to derive the blue color of the brightness but it looks really like in Office 2003])
If you want i can give you the code for this effekt....

arjahn : Your solution works know but i found out, that I only need the Brightness of an RGB-color to realize the blue-effekt.
So I used Sqrt(r²+b²+g²) to derive the brightness. But Thanks....

Commented:
Hi Christoph1987,

>how I can convert RGB to TColor?

Color := RGB(240, 240, 240);

>But i don't like to open a new Question for..

Note, this threads seems to be dead, I do not det e-mail notifications any more (other probably too).

> If you want i can give you the code for this effekt....

Regards,
odissey1

Author Commented:
I know RGB(). But OK!

I use StrToInt('\$' + IntToHex(b,2) + IntToHex(g,2)+ IntToStr(r,2)) to convert RGB to Color.

I will send you the code at weekend...

Bye!
Commented:
Hi ChristopH1987,

>  StrToInt('\$' + IntToHex(b,2) + IntToHex(g,2)+ IntToStr(r,2)) to convert RGB to Color.
-possibly the slowest way! In graphic applications timing is everything. The best is to use pointers or ASM.

odissey1

Author Commented:
Maybe...

But I only need it for little pictures and to inizialize pens...

I have no problems with speed.  Sure, if you want to use it in direct X you will get problems...

I will close this topic now.
Author Commented:
Try this one:

function GetDisabledColor(Brightness : Integer):TColor;
begin
Result := RGB(
Round(109 + (0.32549 * Brightness)),
Round(150 + (0.20392 * Brightness)),
Round(208 + (0.05490 * Brightness)));
end;

// For brightness you have to put in a value between 0 and 255; You should derive it from an RGB-Value... Maybe with
// RGBToHSV() and then put in Round(V)

###### It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.