Solved

# RGB to HVS?

Posted on 2003-11-30
1,398 Views
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??

0
Question by:ChristopH1987
• 6
• 5
• 2
• +1

LVL 5

Accepted Solution

arjanh earned 250 total points
ID: 9844937
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};
0

LVL 2

Author Comment

ID: 9845006
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?
0

LVL 5

Expert Comment

ID: 9845140
// 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.
0

LVL 4

Assisted Solution

StevenB earned 50 total points
ID: 9848350
The comments here might prove enlightening:

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

Regards,
Steven
0

LVL 2

Assisted Solution

odissey1 earned 200 total points
ID: 9848638
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.
0

LVL 2

Expert Comment

ID: 9860994
Hi ChristopH1987,

any success?

regards,
odissey1
0

LVL 2

Expert Comment

ID: 9862188

:(
0

LVL 2

Author Comment

ID: 9865707
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 )
0

LVL 2

Author Comment

ID: 9865741
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....

0

LVL 2

Expert Comment

ID: 9868076
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

0

LVL 2

Author Comment

ID: 9884662
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!
0

LVL 2

Expert Comment

ID: 9885018
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

0

LVL 2

Author Comment

ID: 9887626
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.
0

LVL 2

Author Comment

ID: 9892505
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)

0

## Featured Post

### Suggested Solutions

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usuaâ€¦
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy reâ€¦
Polish reports in Access so they look terrific. Take yourself to another level. Equations, Back Color, Alternate Back Color. Write easy VBA Code. Tighten space to use less pages. Launch report from a menu, considering criteria only when it is filledâ€¦
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Itemsâ€¦