본문 바로가기
Delphi Tip/이미지-영상

델파이 RGB 와 HSL 유틸 유닛

by MonoSoft 2021. 10. 22.
728x90
반응형

델파이 RGB 와 HSL 유틸 유닛

 

HSL의 의미

 

 

HSL은 컬러를 이루는 3가지 요소인 

Hue (색), Saturation (채도), Lightness (명도)를 직접 조절하는 메뉴입니다. 

 

물론 포토샵에서도 Hue / Saturation 모드를 통해 컬러를 조절할 수 있지만

라이트룸은 좀 더 직관적인 메뉴를 제공합니다. 

 

또한 라이트룸에서는 모든 컬러를 동시에 조절하는 것이 아니라

컬러별로 미세하게 위의 요소들을 조절할 수 있기 때문에 보다 

전문적인 컬러 조절을 하기 위해선 꼭 알아야 하는 메뉴입니다.

 

 

unit RGBHSLUtils;

 

interface

 

uses

 

Windows, Graphics, Math, Scanlines;

 

var //set these variables to your needs, e.g. 360, 255, 255

MaxHue: integer = 239;

MaxSat: integer = 240;

MaxLum: integer = 240;

 

function HSLtoRGB (H, S, L: double): TColor;

function HSLRangeToRGB (H, S, L: integer): TColor;

procedure RGBtoHSLRange (RGB: TColor; var H1, S1, L1 : integer);

function GetHValue(AColor: TColor): integer;

function GetSValue(AColor: TColor): integer;

function GetLValue(AColor: TColor): integer;

procedure Clamp(var Input: integer; Min, Max: integer);

function HSLToRGBTriple(H, S, L : integer) : TRGBTriple;

function HSLToRGBQuad(H, S, L: integer): TRGBQuad;

procedure RGBTripleToHSL(RGBTriple : TRGBTriple; var h, s, l: integer);

 

implementation

 

function HSLtoRGB(H, S, L: double): TColor;

var

M1, M2: double;

function HueToColorValue(Hue: double): byte;

var

V : double;

begin

if Hue < 0 then

Hue := Hue + 1

else

if Hue > 1 then

Hue := Hue - 1;

if 6 * Hue < 1 then

V := M1 + (M2 - M1) * Hue * 6

else

if 2 * Hue < 1 then

V := M2

else

if 3 * Hue < 2 then

V := M1 + (M2 - M1) * (2/3 - Hue) * 6

else

V := M1;

Result := round (255 * V)

end;

 

var

R, G, B: byte;

begin

if S = 0 then

begin

R := round (MaxLum * L);

G := R;

B := R

end

else

begin

if L <= 0.5 then

M2 := L * (1 + S)

else

M2 := L + S - L * S;

M1 := 2 * L - M2;

R := HueToColorValue (H + 1/3);

G := HueToColorValue (H);

B := HueToColorValue (H - 1/3)

end;

Result := RGB (R, G, B)

end;

 

function HSLRangeToRGB(H, S, L : integer): TColor;

begin

if s > MaxSat then s := MaxSat;

if s < 0 then s := 0;

if l > MaxLum then l := MaxLum;

if l < 0 then l := 0;

Result := HSLToRGB(H / MaxHue, S / MaxSat, L / MaxLum);

end;

 

procedure RGBtoHSLRange(RGB: TColor; var H1, S1, L1 : integer);

var

R, G, B, D, Cmax, Cmin, h, s, l: double;

begin

H := h1;

S := s1;

L := l1;

R := GetRValue (RGB) / 255;

G := GetGValue (RGB) / 255;

B := GetBValue (RGB) / 255;

Cmax := Max (R, Max (G, B));

Cmin := Min (R, Min (G, B));

L := (Cmax + Cmin) / 2;

if Cmax = Cmin then

begin

H := 0;

S := 0;

end

else

begin

D := Cmax - Cmin;

//calc L

if L < 0.5 then

S := D / (Cmax + Cmin)

else

S := D / (2 - Cmax - Cmin);

//calc H

if R = Cmax then

H := (G - B) / D

else

if G = Cmax then

H := 2 + (B - R) /D

else

H := 4 + (R - G) / D;

H := H / 6;

if H < 0 then

H := H + 1;

end;

 

H1 := round (H * MaxHue);

S1 := round (S * MaxSat);

L1 := round (L * MaxLum);

end;

 

function GetHValue(AColor: TColor): integer;

var

d, h: integer;

begin

RGBToHSLRange(AColor, h, d, d);

Result := h;

end;

 

function GetSValue(AColor: TColor): integer;

var

d, s: integer;

begin

RGBToHSLRange(AColor, d, s, d);

Result := s;

end;

 

function GetLValue(AColor: TColor): integer;

var

d, l: integer;

begin

RGBToHSLRange(AColor, d, d, l);

Result := l;

end;

 

procedure Clamp(var Input: integer; Min, Max: integer);

begin

if (Input < Min) then Input := Min;

if (Input > Max) then Input := Max;

end;

 

function HSLToRGBTriple(H, S, L: integer): TRGBTriple;

const

Divisor = 255*60;

var

hTemp, f, LS, p, q, r: integer;

begin

Clamp(H, 0, MaxHue);

Clamp(S, 0, MaxSat);

Clamp(L, 0, MaxLum);

if (S = 0) then

Result := RGBToRGBTriple(L, L, L)

else

begin

hTemp := H mod MaxHue;

f := hTemp mod 60;

hTemp := hTemp div 60;

LS := L*S;

p := L - LS div MaxLum;

q := L - (LS*f) div Divisor;

r := L - (LS*(60 - f)) div Divisor;

case hTemp of

0: Result := RGBToRGBTriple(L, r, p);

1: Result := RGBToRGBTriple(q, L, p);

2: Result := RGBToRGBTriple(p, L, r);

3: Result := RGBToRGBTriple(p, q, L);

4: Result := RGBToRGBTriple(r, p, L);

5: Result := RGBToRGBTriple(L, p, q);

else

Result := RGBToRGBTriple(0, 0, 0);

end;

end;

end;

 

function HSLToRGBQuad(H, S, L: integer): TRGBQuad;

const

Divisor = 255*60;

var

hTemp, f, LS, p, q, r: integer;

begin

Clamp(H, 0, MaxHue);

Clamp(S, 0, MaxSat);

Clamp(L, 0, MaxLum);

if (S = 0) then

Result := RGBToRGBQuad(L, L, L)

else

begin

hTemp := H mod MaxHue;

f := hTemp mod 60;

hTemp := hTemp div 60;

LS := L*S;

p := L - LS div MaxLum;

q := L - (LS*f) div Divisor;

r := L - (LS*(60 - f)) div Divisor;

case hTemp of

0: Result := RGBToRGBQuad(L, r, p);

1: Result := RGBToRGBQuad(q, L, p);

2: Result := RGBToRGBQuad(p, L, r);

3: Result := RGBToRGBQuad(p, q, L);

4: Result := RGBToRGBQuad(r, p, L);

5: Result := RGBToRGBQuad(L, p, q);

else

Result := RGBToRGBQuad(0, 0, 0);

end;

end;

end;

 

procedure RGBTripleToHSL(RGBTriple: TRGBTriple; var h, s, l: integer);

 

function RGBMaxValue(RGB: TRGBTriple): byte;

begin

Result := RGB.rgbtRed;

if (Result < RGB.rgbtGreen) then Result := RGB.rgbtGreen;

if (Result < RGB.rgbtBlue) then Result := RGB.rgbtBlue;

end;

 

function RGBMinValue(RGB: TRGBTriple) : byte;

begin

Result := RGB.rgbtRed;

if (Result > RGB.rgbtGreen) then Result := RGB.rgbtGreen;

if (Result > RGB.rgbtBlue) then Result := RGB.rgbtBlue;

end;

var

Delta, Min: byte;

begin

L := RGBMaxValue(RGBTriple);

Min := RGBMinValue(RGBTriple);

Delta := L-Min;

if (L = Min) then

begin

H := 0;

S := 0;

end

else

begin

S := MulDiv(Delta, 255, L);

with RGBTriple do

begin

if (rgbtRed = L) then

H := MulDiv(60, rgbtGreen-rgbtBlue, Delta)

else

if (rgbtGreen = L) then

H := MulDiv(60, rgbtBlue-rgbtRed, Delta) + 120

else

if (rgbtBlue = L) then

H := MulDiv(60, rgbtRed-rgbtGreen, Delta) + 240;

if (H < 0) then H := H + 360;

end;

end;

end;

end.

 

728x90
반응형

댓글