Code archives/Algorithms/RGB to HSB and back

This code has been declared by its author to be Public Domain code.

Download source code

RGB to HSB and back by jfk EO-11110
(Posted 22 years ago)
RGB2HSB and HSB2RGB - can be used for altering Hue, Saturation or Brightness (Luminance) independently in an easy way. Then after editing you simply convert it back to RGB.
; sorry for the Gotos :P
Graphics 640,480,32,2
SetBuffer BackBuffer()

Global sat#,lumin#,hue#

; test demo
While KeyDown(1)=0
 sat#=0
 lumin#=0
 hue#=0
 r=Rand(255)
 g=Rand(255)
 b=Rand(255)
 Color r,g,b
 Cls
 Rect 100,100,100,100,1 ; draw in original rgb
 rgb2hsb(rgb(r,g,b))    ; convert to hsb
 rgb=hsb2rgb(hue,sat,lumin)  ; convert back to rgb
 Color getRed(rgb),getGreen(rgb),getBlue(rgb)  ; draw again
 Rect 100,220,100,100,1

 Locate 0,0
 Print "R: "+r
 Print "G: "+g
 Print "B: "+b
 Print
 Print "Hue:   "+hue
 Print "Sat:   "+sat
 Print "Lumin: "+lumin
 Print
 Print "Convert back"
 Print "R2: "+getRed(rgb)
 Print "G2: "+getGreen(rgb)
 Print "B2: "+getBlue(rgb)
 Locate 0,GraphicsHeight()-50
 Print "Press a key to continue, Esc to exit"
 Flip
 WaitKey()

Wend
End


Function hsb2rgb(h#,s#,l#) ; takes hue(0 to 360), saturation (0 to 1.0) and luminance (0 to 1.0)
 Local i,f#,p#,q#,t#,r#,g#,b#
 If s=0
  r=l*255.0:g=l*255.0:b=l*255.0
 Else
  h=h/60.0
  i=Floor(h)
  f=h-i
  p=l*(1.0-s)
  q=l*(1.0-s*f)
  t=l*(1.0-s*(1.0-f))
  Select i
   Case 0
    r=l
    g=t
    b=p
   Case 1
    r=q
    g=l
    b=p
   Case 2
    r=p
    g=l
    b=t
   Case 3
    r=p
    b=l
    g=q
   Case 4
    r=t
    b=l
    g=p
   Default
    r=l
    g=p
    b=q
  End Select
  r=r*255
  g=g*255
  b=b*255
 EndIf
 If r<0 Then r=0
 If r>255 Then r=255
 If g<0 Then g=0
 If g>255 Then g=255
 If b<0 Then b=0
 If b>255 Then b=255
 rgb=(r Shl 16)Or(g Shl 8)Or b
 Return rgb
End Function



Function rgb2hsb(rgb) ; takes 24 bit rgb color, returns (global) hue(0 to 360), saturation(0 to 1.0) and luminance(0 to 1.0)
 rgb=rgb And $FFFFFF
 r#=(rgb Shr 16) And $FF
 g#=(rgb Shr 8) And $FF
 b#=rgb And $FF
 my_min#=min#(r,g)
 my_max#=max#(r,g)
 my_min#=min#(my_min#,b)
 my_max#=max#(my_max#,b)
 delta#=(my_max#-my_min#)
 If my_max#<>0
  sat#=delta#/my_max#
  lumin#=my_max#/255.0
  If delta<>0
   If r=my_max Then 
    hue=(g-b)/delta
    Goto okii
   EndIf
   If g=my_max Then 
    hue=2+((b-r)/delta)
    Goto okii
   EndIf
   hue=4+((r-g)/delta)
   .okii
  EndIf
 EndIf
 hue=hue*60.0
 If hue<0 Then hue=hue+360.0
End Function



Function rgb(r,g,b)
 Return (r Shl 16) Or (g Shl 8) Or b
End Function

Function getRed(rgb)
 Return (rgb And $FF0000) Shr 16
End Function

Function getGreen(rgb)
 Return (rgb And $FF00) Shr 8
End Function

Function getBlue(rgb)
 Return (rgb And $FF)
End Function

Function min#(v1#,v2#)
 If v1<v2 Then 
  Return v1
 Else
  Return v2
 EndIf
End Function

Function max#(v1#,v2#)
 If v1>v2 Then 
  Return v1
 Else
  Return v2
 EndIf
End Function

Comments

big10p
(Posted 22 years ago)
As requested, here are my versions.

I converted these from C code I found in a Foley & Van Dam graphics book. However, the original C code uses double precision floats - which we don't have - so there will probably be a small amount of inaccuracy sometimes. Not much I can do about that. :)

	; RGB/HSL function return values.
	Global result_r#, result_g#, result_b#		
	Global result_h#, result_s#, result_l#

;
; Converts an RGB color to HSL.
;
; Params:
; ir,ig,ib - Color's red, green and blue components (0-255).
;
; Returns:
;	The converted color's HSL values via the following globals:
; result_h - Hue component (0-360).
; result_s - Saturation component (0-1).
; result_l - Luminance component (0-1).
;
Function rgb_to_hsl(ir%, ig%, ib%)

	; Scale RGB down to unit range (0-1).
	r# = ir/255.0
	g# = ig/255.0
	b# = ib/255.0
	
	If r > g
		max_is = 0
		max_color# = r
		min_color# = g
	Else
		max_is = 1
		max_color# = g
		min_color# = r
	EndIf
	
	If b > max_color
		max_is = 2
		max_color = b
	ElseIf b < min_color
		min_color = b
	EndIf
	
	; Luminance.
	result_l = (max_color + min_color) / 2.0

	If max_color = min_color
		; Color is grey.
		result_s = 0
		;result_h = 0
	Else
		delta# = (max_color - min_color)

		; Saturation.
		If result_l < 0.5
			result_s = delta / (max_color + min_color)
		Else
			result_s = delta / (2.0 - max_color - min_color)
		EndIf
	
		; Hue.
		Select max_is
		Case 0
			; Red.
			result_h = (g - b) / delta
		Case 1
			; Green.
			result_h = 2.0 + (b - r) / delta
		Case 2
			; Blue.
			result_h = 4.0 + (r - g) / delta
		End Select

		result_h = result_h * 60.0
		If result_h < 0 Then result_h = result_h + 360.0
	EndIf

End Function


;
; Converts an HSL color to RGB.
;
; Params:
; h,s,l - Color's hue(0-360), luminance(0-1) and saturation(0-1) components.
;
; Returns:
;	The converted color's RGB values via the following globals:
; result_r - Hue component (0-255).
; result_g - Saturation component (0-255).
; result_b - Luminance component (0-255).
;
Function hsl_to_rgb(h#, s#, l#)

	If s = 0
		result_r# = l
		result_g# = l
		result_b# = l
	Else
		If l < 0.5
			temp2# = l * (1.0 + s)
		Else
			temp2# = (l + s) - (l * s)
		EndIf
		temp1# = 2.0 * l - temp2
		
		h = h / 360.0
		
		rtemp3# = h + 1.0 / 3.0
		If rtemp3 < 0
			rtemp3 = rtemp3 + 1.0
		ElseIf rtemp3 > 1
			rtemp3 = rtemp3 - 1.0
		EndIf

		gtemp3# = h
		If gtemp3 < 0
			gtemp3 = gtemp3 + 1.0
		ElseIf gtemp3 > 1
			gtemp3 = gtemp3 - 1.0
		EndIf

		btemp3# = h - 1.0 / 3.0
		If btemp3 < 0
			btemp3 = btemp3 + 1.0
		ElseIf btemp3 > 1
			btemp3 = btemp3 - 1.0
		EndIf
		
		; Set red.
		If (6.0 * rtemp3) < 1
			result_r# = temp1 + (temp2 - temp1) * 6.0 * rtemp3
		ElseIf (2.0 * rtemp3) < 1
			result_r# = temp2
		ElseIf (3.0 * rtemp3) < 2
			result_r# = temp1 + (temp2 - temp1) * ((2.0 / 3.0) - rtemp3) * 6.0
		Else
			result_r# = temp1
		EndIf

		; Set green.
		If (6.0 * gtemp3) < 1
			result_g# = temp1 + (temp2 - temp1) * 6.0 * gtemp3
		ElseIf (2.0 * gtemp3) < 1
			result_g# = temp2
		ElseIf (3.0 * gtemp3) < 2
			result_g# = temp1 + (temp2 - temp1) * ((2.0 / 3.0) - gtemp3) * 6.0
		Else
			result_g# = temp1
		EndIf

		; Set blue.
		If (6.0 * btemp3) < 1
			result_b# = temp1 + (temp2 - temp1) * 6.0 * btemp3
		ElseIf (2.0 * btemp3) < 1
			result_b# = temp2
		ElseIf (3.0 * btemp3) < 2
			result_b# = temp1 + (temp2 - temp1) * ((2.0 / 3.0) - btemp3) * 6.0
		Else
			result_b# = temp1
		EndIf
	EndIf

	; Scale RGB back to 0-255 range.
	; Remove this if you want to keep RGB in the range 0-1!
	result_r = result_r * 255
	result_g = result_g * 255
	result_b = result_b * 255

End Function


jfk EO-11110
(Posted 22 years ago)
thanks.

Code Archives Forum