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??


Thanks for advance!
LVL 2
ChristopH1987Asked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

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.

arjanhCommented:
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

Your issues matter to us.

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

Start your 7-day free trial
ChristopH1987Author 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?
arjanhCommented:
// 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.
Python 3 Fundamentals

This course will teach participants about installing and configuring Python, syntax, importing, statements, types, strings, booleans, files, lists, tuples, comprehensions, functions, and classes.

StevenBCommented:
The comments here might prove enlightening:

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


Regards,
Steven
odissey1Commented:
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;
function AdjustGamma(Color: double): Integer;
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);
              k:=AdjustGamma(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.
odissey1Commented:
Hi ChristopH1987,

any success?

regards,
odissey1
odissey1Commented:
This thread is dead or something...

:(
ChristopH1987Author 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!


Thanks for Advance.

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 )
ChristopH1987Author 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....




odissey1Commented:
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....

Yes, please. Could you drop it to 'botadjik@nmsu.edu'?

Regards,
odissey1


ChristopH1987Author 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!
odissey1Commented:
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

ChristopH1987Author 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...


Thanks for Advance!


I will close this topic now.
ChristopH1987Author 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.