C Formula That Converts HSL to RGB()

Just starting out? Need help? Post your questions and find answers here.
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: C Formula That Converts HSL to RGB()

Post by wilbert »

This page also contains some information about such a RGB to HSL formula
http://lolengine.net/blog/2013/01/13/fast-rgb-to-hsv

Here's some code based on the information I found on that page.
It should give the same results.

Code: Select all

Procedure RGB2HSL(R, G, B, *H.Float, *S.Float, *L.Float)
  Protected.l k
  If G < B : Swap G, B : k = 360 : EndIf
  If R < G : Swap R, G : k = 120 - k : EndIf
  If G < B
    *H\f = R - G : *L\f = R + G 
  Else
    *H\f = R - B : *L\f = R + B 
  EndIf
  *S\f = 100 * *H\f / (255 - Abs(*L\f - 255) + 1e-20)
  *H\f = Abs(60 * (G - B) / (*H\f + 1e-20) - k)
  *L\f / 5.1
EndProcedure


Define.f hue, sat, lum

RGB2HSL(174, 155, 110, @hue, @sat, @lum)

Debug hue
Debug sat
Debug lum
Windows (x64)
Raspberry Pi OS (Arm64)
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: C Formula That Converts HSL to RGB()

Post by RASHAD »

Yes it does
And thanks for the link
Egypt my love
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: C Formula That Converts HSL to RGB()

Post by Dude »

RASHAD wrote:thanks for CMYK converter
I actually just fixed my CMYK code above to handle RGB(0,0,0). :oops:
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: C Formula That Converts HSL to RGB()

Post by Michael Vogel »

Nice functions, what about the other way around?

RGB2HSL and HSL2RGB, RGB2CMYK and CMYK2RGB?

Maybe the latter would help to greate a tool which allows to calculate how to mix several paint colors to achieve a certain colour tone.
Dude
Addict
Addict
Posts: 1907
Joined: Mon Feb 16, 2015 2:49 pm

Re: C Formula That Converts HSL to RGB()

Post by Dude »

Michael Vogel wrote:Nice functions, what about the other way around?
The page I linked to has the math (it's how I worked out my RGB to CMYK formula), but HSL to RGB is way above my understanding:

https://www.rapidtables.com/convert/col ... o-rgb.html

No way I can work that out. :shock: CMYK to RGB looks easy (https://www.rapidtables.com/convert/col ... o-rgb.html).

Image
RASHAD
PureBasic Expert
PureBasic Expert
Posts: 4946
Joined: Sun Apr 12, 2009 6:27 am

Re: C Formula That Converts HSL to RGB()

Post by RASHAD »

Hi

Code: Select all

Global hue.f,sat.f,lum.f

Procedure  RGB2HSL(color)
  Protected r.f,g.f,b.f,cmax.f,cmin.f,c.f
  r = Red(color) / 255
  g = Green(color) / 255
  b = Blue(color) / 255
  Dim a.f(2)
  a(0) = r : a(1) = g : a(2) = b
  SortArray(a.f(),#PB_Sort_Ascending )
  cmax = a(2)
  cmin = a(0)
  lum = (cmax + cmin) / 2
  If cmax = cmin
      hue = 0
      sat = 0
  Else
    c = cmax - cmin
    sat = c / (1 - Abs(2 * lum - 1))
    If r = cmax
      hue = (g - b) / c
    ElseIf g = cmax
      hue = (b - r) / c + 2             
    ElseIf b = cmax
      hue = (r - g) / c + 4             
    EndIf
  EndIf
EndProcedure

Procedure.f Hue2RGB(v1.f, v2.f, vH.f)
   If vH < 0 : vH + 1 : EndIf
   If vH > 1 : vH - 1 : EndIf
   If (6 * vH) < 1 : ProcedureReturn (v1 + (v2 - v1) * 6 * vH) : EndIf
   If (2 * vH) < 1 : ProcedureReturn v2 : EndIf
   If (3 * vh) < 2 : ProcedureReturn (v1 + (v2 - v1) * ((2.0 / 3.0) - vH) * 6) : EndIf
   
   ProcedureReturn v1
EndProcedure

Procedure.l HSL2RGB(H.f, S.f, L.f)
   
   Protected.i R, G, B
   Protected.f var_1, var_2
   
   If S = 0
      R = L * 255
      G = L * 255
      B = L * 255
   Else
      If L < 0.5
         var_2 = L * (1 + S)
      Else
         var_2 = (L + S) - (S * L)
      EndIf
         
      var_1 = 2 * L - var_2
     
      R = 255 * Hue2RGB(var_1, var_2, H + (1.0 / 3.0))
      G = 255 * Hue2RGB(var_1, var_2, H)
      B = 255 * Hue2RGB(var_1, var_2, H - (1.0 / 3.0))
   EndIf
   
   ProcedureReturn (R | G<<8 | B<<16)
EndProcedure

LoadFont(0,"Tahoma",12,#PB_Font_Bold)
SetGadgetFont(#PB_Default,FontID(0))

OpenWindow(0,0,0,275,145,"",#PB_Window_SystemMenu  |#PB_Window_Tool|#PB_Window_ScreenCentered)

SetWindowTitle(0,Space(20)+"RGB  <-->  HSL")
SpinGadget(0,40,10,80,24,0,255, #PB_Spin_Numeric)
SetGadgetState(0,0)
text = TextGadget(#PB_Any,10,10,24,24,"")
SpinGadget(1,40,40,80,24,0,255, #PB_Spin_Numeric)
SetGadgetState(1,0)
text1 = TextGadget(#PB_Any,10,40,24,24,"")
SpinGadget(2,40,70,80,24,0,255, #PB_Spin_Numeric)
SetGadgetState(2,0)
text2 = TextGadget(#PB_Any,10,70,24,24,"")
SpinGadget(3,150,10,80,24,0,360, #PB_Spin_Numeric)
SetGadgetState(3,0)
text3 = TextGadget(#PB_Any,240,10,24,24,Chr(176),#PB_Text_Center)
SpinGadget(4,150,40,80,24,0,255, #PB_Spin_Numeric)
SetGadgetState(4,0)
text4 = TextGadget(#PB_Any,240,40,24,24,"%",#PB_Text_Center)
SpinGadget(5,150,70,80,24,0,255, #PB_Spin_Numeric)
SetGadgetState(5,0)
text5 = TextGadget(#PB_Any,240,70,24,24,"%",#PB_Text_Center)

SetGadgetColor(text,#PB_Gadget_BackColor,$CCCCCD)
SetGadgetColor(text1,#PB_Gadget_BackColor,$CCCCCD)
SetGadgetColor(text2,#PB_Gadget_BackColor,$CCCCCD)

ButtonGadget(10,10,110,80,26,"►")
ButtonGadget(20,185,110,80,26,"◄")

Repeat 
  Select WaitWindowEvent()
    Case #PB_Event_CloseWindow
        Quit = 1
        
    Case #PB_Event_Gadget
      Select EventGadget()
        Case 0,1,2
          red = GetGadgetState(0)
          green = GetGadgetState(1)
          blue = GetGadgetState(2)
          SetGadgetColor(text,#PB_Gadget_BackColor,RGB(red,0,0))
          SetGadgetColor(text1,#PB_Gadget_BackColor,RGB(0,green,0))
          SetGadgetColor(text2,#PB_Gadget_BackColor,RGB(0,0,blue))
          
        Case 10
          red = GetGadgetState(0)
          green = GetGadgetState(1)
          blue = GetGadgetState(2)
          color = RGB(red,green,blue)
          RGB2HSL(color)
          hue = Round(hue * 60,#PB_Round_Nearest)   ;  °
          If hue < 0
            hue = 360 + hue
          EndIf
          sat = Round(sat * 100,#PB_Round_Nearest)  ;  %
          lum = Round(lum * 100,#PB_Round_Nearest)  ;  %
          SetGadgetState(3,hue)
          SetGadgetState(4,sat)
          SetGadgetState(5,lum)
          hue = 0:sat = 0:lum = 0
          
        Case 20
          hue.f = GetGadgetState(3)/360
          sat.f = GetGadgetState(4)/100
          lum.f = GetGadgetState(5)/100
          color.i = HSL2RGB(hue.f, sat.f, lum.f)
          SetGadgetState(0,Red(color))
          SetGadgetColor(text,#PB_Gadget_BackColor,RGB(Red(color),0,0))
          SetGadgetState(1,Green(color))
          SetGadgetColor(text1,#PB_Gadget_BackColor,RGB(0,Green(color),0))
          SetGadgetState(2,Blue(color))
          SetGadgetColor(text2,#PB_Gadget_BackColor,RGB(0,0,Blue(color)))
          hue = 0:sat = 0:lum = 0          
      EndSelect
  EndSelect
Until Quit = 1
Egypt my love
wilbert
PureBasic Expert
PureBasic Expert
Posts: 3942
Joined: Sun Aug 08, 2004 5:21 am
Location: Netherlands

Re: C Formula That Converts HSL to RGB()

Post by wilbert »

Michael Vogel wrote:RGB2CMYK and CMYK2RGB?
Integer
RGB [0,255]
CMYK [0,100]

Code: Select all

Procedure RGB2CMYK(R,G,B, *C.Ascii, *M.Ascii, *Y.Ascii, *K.Ascii)
  Protected.i K=R, M
  If G>K : K=G : EndIf
  If B>K : K=B : EndIf
  If K : M=$64000000/K : EndIf
  *C\a = ((K-R)*M+$800000)>>24
  *M\a = ((K-G)*M+$800000)>>24
  *Y\a = ((K-B)*M+$800000)>>24
  *K\a = (K!$ff*$646464+$800000)>>24
EndProcedure

Procedure CMYK2RGB(C,M,Y,K, *R.Ascii, *G.Ascii, *B.Ascii)
  K=(100-K)*$6872c
  *R\a = ((100-C)*K+$800000)>>24
  *G\a = ((100-M)*K+$800000)>>24
  *B\a = ((100-Y)*K+$800000)>>24
EndProcedure



RGB2CMYK(255,128,0, @C,@M,@Y,@K)
Debug C
Debug M
Debug Y
Debug K

CMYK2RGB(0,50,100,0, @R,@G,@B)
Debug R
Debug G
Debug B
Floats
RGB [0, 255]
CMYK [0.0 , 1.0]

Code: Select all

Procedure RGB2CMYK(R, G, B, *C.Float, *M.Float, *Y.Float, *K.Float)
  Protected K.i=R, M.f
  If G>K : K=G : EndIf
  If B>K : K=B : EndIf
  If K : M=1/K : EndIf
  *C\f = (K-R)*M
  *M\f = (K-G)*M
  *Y\f = (K-B)*M
  *K\f = 1-K/255
EndProcedure

Procedure CMYK2RGB(C.f, M.f, Y.f, K.f, *R.Ascii, *G.Ascii, *B.Ascii)
  K=(1-K)*255
  *R\a = (1-C)*K
  *G\a = (1-M)*K
  *B\a = (1-Y)*K
EndProcedure



RGB2CMYK(4,20,5, @C.f,@M.f,@Y.f,@K.f)
Debug C
Debug M
Debug Y
Debug K

CMYK2RGB(C,M,Y,K, @R,@G,@B)
Debug R
Debug G
Debug B
Windows (x64)
Raspberry Pi OS (Arm64)
User avatar
Michael Vogel
Addict
Addict
Posts: 2797
Joined: Thu Feb 09, 2006 11:27 pm
Contact:

Re: C Formula That Converts HSL to RGB()

Post by Michael Vogel »

Great job, Rashad and Wilbert :!:

Just put all parts together to work with integer values (Saturation and Lumination can be set for percent or thousandth by changing the factor constant):

Code: Select all

; RGB	0-255
; CMYK	0-100
; HSL	0-359°, 0-100/1000

#Factor=1000

Procedure.f HUE2COL(l.f,s.f,h.f)

	l=l*2-s
	If h<0 : h+1 : ElseIf h>1 : h-1 : EndIf

	If h*6<1 : ProcedureReturn (l+(s-l)*6*h) : EndIf
	If h*2<1 : ProcedureReturn s : EndIf
	If h*3<2 : ProcedureReturn (l+(s-l)*(2/3-h)*6) : EndIf

	ProcedureReturn l

EndProcedure
Procedure RGB2HSL(R.f,G.f,B.f,*hue.Integer,*sat.Integer,*lum.Integer)

	Protected min.f,max.f
	Protected c.f

	R/255 : G/255 : B/255

	max=R : min=R
	If min>G : min=G : EndIf
	If min>B : min=B : EndIf
	If max<G : max=G : EndIf
	If max<B : max=B : EndIf

	*lum\i=(min+max)*#Factor/2

	If max-min
		c=max-min
		*sat\i=#Factor*c / (1 - Abs(min+max-1))
		If r=max
			*hue\i=60*(g-b)/c
		ElseIf g=max
			*hue\i=60*(b-r)/c+120
		ElseIf b=max
			*hue\i=60*(r-g)/c+240
		EndIf

	Else
		*hue\i=0
		*sat\i=0

	EndIf

EndProcedure
Procedure HSL2RGB(Hue.f,Sat.f,Lum.f,*R.Integer,*G.Integer,*B.Integer)

	Hue/360
	Sat/#Factor
	Lum/#Factor

	If Sat=0
		Lum*255
		*R\i=Lum
		*G\i=Lum
		*B\i=Lum

	Else
		If Lum<0.5
			Sat=Lum*(1+Sat)
		Else
			Sat=(Lum+Sat)-(Sat*Lum)
		EndIf

		*R\i=255*HUE2COL(Lum,Sat,Hue+1/3)
		*G\i=255*HUE2COL(Lum,Sat,Hue)
		*B\i=255*HUE2COL(Lum,Sat,Hue-1/3)

	EndIf

EndProcedure
Procedure RGB2CMYK(R,G,B,*C.Integer,*M.Integer,*Y.Integer,*K.Integer)

	Protected.i K,M

	K=R
	If G>K : K=G : EndIf
	If B>K : K=B : EndIf
	If K : M=$64000000/K : EndIf

	*C\i = ((K-R)*M+$800000)>>24&$FF
	*M\i = ((K-G)*M+$800000)>>24&$FF
	*Y\i = ((K-B)*M+$800000)>>24&$FF
	*K\i = (K!$ff*$646464+$800000)>>24&$FF

EndProcedure
Procedure CMYK2RGB(C,M,Y,K,*R.Integer,*G.Integer,*B.Integer)

	K=(100-K)*$6872c

	*R\i = ((100-C)*K+$800000)>>24&$FF
	*G\i = ((100-M)*K+$800000)>>24&$FF
	*B\i = ((100-Y)*K+$800000)>>24&$FF

EndProcedure

For i=1 To 4
	
	Debug ""
	Debug "Conversion "+Mid(" :)  RGB > CMYK> RGB > HSL > RGB",i*6,10)
	
	Select i
	Case 1
		RGB2CMYK(66,111,222,@C,@M,@Y,@K)
		Debug C
		Debug M
		Debug Y
		Debug K

	Case 2
		CMYK2RGB(C,M,Y,K,@R,@G,@B)
		Debug R
		Debug G
		Debug B

	Case 3
		RGB2HSL(R,G,B,@hue,@sat,@lum)
		Debug Str(hue)+"°"
		Debug StrF(sat/10,1)+"%"
		Debug StrF(lum/10,1)+"%"

	Case 4
		HSL2RGB(hue,sat,lum,@R,@G,@B)
		Debug R
		Debug G
		Debug B

	EndSelect

Next i
Anyhow, I am not sure why CorelDraw says CMYK(50,100,50,0) = RGB(150,48,90) but the functions above show CMYK(50,100,50,0) = RGB(128,0,128)
Oma
Enthusiast
Enthusiast
Posts: 312
Joined: Thu Jun 26, 2014 9:17 am
Location: Germany

Re: C Formula That Converts HSL to RGB()

Post by Oma »

First, thank you all for your examples.
With the existing examples and other solutions on the web I also made myself a converter between RGB, HSL, HSV, CMYK in the last days.
@Michael Vogel
And I also noticed the different results of other CMYK converters.

I / we assume that C, M, Y, K have the following PB-Format-RGB-values at 100%:
C: $FFFF00
M: $FF00FF
Y: $00FFFF
K: $0
Other models are based on other color values at 100% (more printer-/paper-compatible), e.g. :
C: $EFAE00
M: $8C00EC
Y: $00F2FF
K: $201F23

So the RGB value are different.

Regards, Charly
PureBasic 5.4-5.7, Linux: (X/L/K)Ubuntus+Mint - Windows XP (32Bit)
PureBasic Linux-API-Library & Viewer: http://www.chabba.de
Post Reply