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 )

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 )
R := GetRValue(RGBColor);
G := GetGValue(RGBColor);
B := GetBValue(RGBColor);
( wylicz jasność )
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 )
S := 0; ( Nasycenie (Saturation) )
H := UNDEFINED; ( Barwa (Hue) )
end
else
begin

( przypadek barwny )

<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)(((HLSMAX2) 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 )
B := (LumRGBMAX) 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>

<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