Konwersja RGB na HSL i odwrotnie

Dryobates

Przedstawiony tu sposób zaokrągla trochę wartości, żeby obliczenia przechodziły szybciej. Jednak błędy wynikające z zaokrągleń są niewielkie i w większości zastosowań można ten sposób stosować.

uses
Math;

const
HLSMAX = 255; (* Może to być dowolna inna wartość <= 255. Dobrze by było, żeby dzieliła się przez 6. Wówczas najmniejsze są błędy wynikające z zaokrągleń )
RGBMAX = 255;
(
Barwa (Hue) jest nieokreślona jeżeli Nasycenie (Saturation) jest róne 0 (odcienie szarości) )
(
Ta wartość określa, wartość Hue, jeżeli kolor jest bezbarwny )
</span>
UNDEFINED = (HLSMAX
2 div 3);

procedure RGBtoHLS(RGBColor: TColor; var H, L, S: Byte);
var
R, G, B: Byte;
cMax, cMin: Byte; (* maksymalna i minimalna wartość RGB*)
RDelta,GDelta,BDelta: Word; (* Wartości pośrednie: % wartości maksymalnej )
begin
(
wyciągnij wartości R, G, i B z koloru )</span>
R := GetRValue(RGBColor);
G := GetGValue(RGBColor);
B := GetBValue(RGBColor);
(
wylicz jasność )</span>
cMax := Max(Max(R, G), B);
cMin := Min(Min(R, G), B);
L := (((cMax + cMin)HLSMAX) + RGBMAX ) div (2RGBMAX);
if cMax = cMin then
begin

(
r=g=b --> przypadek bezbarwny )</span>
S := 0; (
Nasycenie (Saturation) )</span>
H := UNDEFINED; (
Barwa (Hue) )</span>
end
else
begin

(
przypadek barwny *)</span>

<span style="color: #000088"><i>(* Nasycenie (Saturation) *)</i></span>
<b>if</b> L <= (HLSMAX <b>div</b> 2) <b>then</b>
  S := (((cMax - cMin)*HLSMAX) + ((cMax + cMin) <b>div</b> 2)) <b>div</b> (cMax + cMin)
<b>else</b>
  S := (((cMax - cMin)*HLSMAX) + ((2*RGBMAX - cMax - cMin) <b>div</b> 2)) <b>div</b> (2*RGBMAX - cMax - cMin);
<span style="color: #000088"><i>(* Barwa (Hue) *)</i></span>
  RDelta := (((cMax - R)*(HLSMAX <b>div</b> 6)) + ((cMax - cMin) <b>div</b> 2)) <b>div</b> (cMax - cMin);
  GDelta := (((cMax - G)*(HLSMAX <b>div</b> 6)) + ((cMax - cMin) <b>div</b> 2)) <b>div</b> (cMax - cMin);
  BDelta := (((cMax - B)*(HLSMAX <b>div</b> 6)) + ((cMax - cMin) <b>div</b> 2)) <b>div</b> (cMax - cMin);
<b>if</b> R = cMax <b>then</b>
  H := BDelta - GDelta
<b>else</b>
  <b>if</b> G = cMax <b>then</b>
    H := (HLSMAX <b>div</b> 3) + RDelta - BDelta
  <b>else</b> <span style="color: #000088"><i>(* B = cMax *)</i></span>
    H := ((2*HLSMAX) <b>div</b> 3) + GDelta - RDelta;

end;
end;

function HLStoRGB(Hue, Lum{inosity}, Sat{uration}: Byte): TColor;

function HueToRGB(n1, n2, Hue: Byte): Byte;
begin
Result := n1;
(* Zwraca wartość R, G lub B )
if Hue < (HLSMAX div 6) then
begin

Result := (n1 + (((n2 - n1)Hue + (HLSMAX div 12)) div (HLSMAX div 6)) );
Exit;
end;
if Hue < (HLSMAX div 2) then
begin

Result := n2;
Exit;
end;
if Hue < ((HLSMAX
2) div 3) then
begin

Result := (n1 + (((n2 - n1)
(((HLSMAX*2) div 3) - Hue)+(HLSMAX div 12)) div (HLSMAX div 6)));
Exit;
end;
end;

var
R, G, B: Byte;
Magic1, Magic2: Word; (* wylicza magiczne liczby )
begin
if Sat = 0 then
begin

(
przypadek bezbarwny )</span>
B := (Lum
RGBMAX) div HLSMAX;
R := B;
G := B;
if Hue <> UNDEFINED </b>then
raise</b> EConvertError.Create('Błędna wartość Hue');
end
else
begin

(* przypadek barwny *)

<span style="color: #000088"><i>(* wylicz magiczne liczby *)</i></span>
<b>if</b> Lum <= (HLSMAX <b>div</b> 2) <b>then</b>
  Magic2 := (Lum*(HLSMAX + Sat) + (HLSMAX <b>div</b> 2)) <b>div</b> HLSMAX
<b>else</b>
  Magic2 := Lum + Sat - ((Lum*Sat) + (HLSMAX <b>div</b> 2)) <b>div</b> HLSMAX;
Magic1 := 2*Lum - Magic2;

<span style="color: #000088"><i>(* Wylicz RGB; zmień HLSMAX na RGBMAX *)</i></span>
R := (HueToRGB(Magic1, Magic2, Hue + (HLSMAX <b>div</b> 3))*RGBMAX + (HLSMAX <b>div</b> 2)) <b>div</b> HLSMAX;
G := (HueToRGB(Magic1, Magic2, Hue)*RGBMAX + (HLSMAX <b>div</b> 2)) <b>div</b> HLSMAX;
B := (HueToRGB(Magic1, Magic2, Hue - (HLSMAX <b>div</b> 3))*RGBMAX + (HLSMAX <b>div</b> 2)) <b>div</b> HLSMAX;

end;
Result := RGB(R, G, B);
end;
</delphi>

0 komentarzy