[Library] HSL & HSV v0.1 (Preview) - Convert RGB To/From HSL or HSV

Post your working scripts, libraries and tools
User avatar
jballi
Posts: 616
Joined: 29 Sep 2013, 17:34

[Library] HSL & HSV v0.1 (Preview) - Convert RGB To/From HSL or HSV

22 Apr 2017, 21:13

Introduction
From Wikipedia:

HSL and HSV are the two most common cylindrical-coordinate representations of points in an RGB color model. HSL and HSV are used today in color pickers, in image editing software, and less commonly in image analysis and computer vision.

HSL stands for hue, saturation, and lightness (or luminosity), and is also often called HLS. HSV stands for hue, saturation, and value, and is also often called HSB (B for brightness).


This post contains two small libraries. The HSL library converts RGB (Red, Green, Blue) color values to and from HSL. The HSV library converts RGB color values to and from HSV.

I am not the author of these functions. I just extracted the code from the interwebs and made minor modifications to get them to work on AutoHotkey and to provide consistent input and output formats. See the References section for more information.

The Code
The pertinent files for the HSL library are as follows:
  • Project: HSL.zip (Includes the library, example scripts, and links to web sites to confirm the results)
  • Documentation: HSL.html
The pertinent files for the HSV library are as follows:
  • Project: HSV.zip (Includes the library, example scripts, and links to web sites to confirm the results)
  • Documentation: HSV.html
Issues/Considerations
A few considerations:
  • Which library? Both libraries do basically the same thing but they go about it differently. See the Wikipedia article in the References section for more information. Both models are widely used. In the "Choose Color" dialog, Microsoft uses the HSL model. Also, the CSS 3 specification allows web developers to specify colors directly with HSL values. According to this article, HSV is often used by artists. Many image editing programs (Ex: Photoshop) use the HSV model.
  • Why are the input/output values a number between 0 and 1? All functions in both libraries require that all input values be a number from 0 to 1 and all return values are a number from 0 to 1. The primary reason is accuracy. A real number between 0 and 1 allows for billions of possible values whereas limiting the values to integers (0 to 100, 0 to 240, 0 to 255, 0 to 360, etc.) significantly limits the accuracy of the conversion. Another reason is flexibility. Although most RGB conversions are done for True Color (i.e. 24-bit color values), a real number input/output allows for easy adaptation to Deep Color (30/36/48-bit color values). For the other values, an input/output number between 0 and 1 allows the developer to determine the level of accuracy.
  • Real Numbers: Internal vs. Display. The functions in these libraries do a lot of calculations with real numbers. By default, AutoHotkey will internally use 15 digits of precision for real (also known as float or floating) numbers but when these numbers are displayed (Ex: MsgBox, Outputdebug, etc.) or converted to strings, they are displayed with only 6 digits of precision. For example, the internal value might be 0.366666608774191 but will displayed as 0.366667. Note that in this example, the display version of the number is a rounded version of the internal number with 6 digits of precision. In rare situations, the discrepancy between the internal number and the display number can cause confusion. For example, if 0.366666608774191 is converted to a color between 0 and 255 (Ex: Color:=Round(MyRealNumber*255)), the result would correctly be 93. However, if this same calculation is performed manually using the display version of the number (i.e. 0.366667), the result will be 94. Although not recommended, AutoHotkey can be forced to use the same internal and display format with the SetFormat Float command.
  • Testing. Although I've tested the heck out of these functions, it's almost impossible to test all possible values. If you find any bugs, please let me know. I will try to resolve the problem.
References
Final Thoughts
I developed these libraries for a single "for fun" project to display and allow sorting of the Hue, Saturation, and Luminous values of a list of HTML colors. For most AutoHotkey developers, this is a low/no value project but I'm releasing it just in case someone needs it.

Release Notes
Helgef
Posts: 4440
Joined: 17 Jul 2016, 01:02
Contact:

Re: [Library] HSL & HSV v0.1 (Preview) - Convert RGB To/From HSL or HSV

05 Jul 2017, 03:47

Hi jballi.
I saw this when you first posted, I tried it and it works well, but I forgot to respond. I saw this topic in the ask for help section, and was reminded, this is a good example of when this kinds of transformations are useful, of course, it is slow in script code, consider this an example of usage.

Code: Select all

; HSL example.
;#include gdip.ahk 
#include HSL\HSL.ahk
setbatchlines,-1
listlines,off
#noenv

; Settings
showProgress:=true
updateRate:=10000	; If showing progress, update every updateRate pixel (default: 10000)

; Factor settings
; 1 	-> no change
; 1.1 -> increase 10 %
; 0.9 -> decrease 10 %
factor_h:=1
factor_s:=1
factor_l:=1

; Source
hbmp:=LoadPicture("myImage.bmp", "w128 h-1") 	; For testing
;hbmp:=LoadPicture("myImage.bmp") ; When happy with test results - do the full image

; Preview - before
gui, new
Gui,Font,s14,Courier new
gui,add,text,,Before:
gui, add, pic,, % "hBitmap:" hbmp

pToken := Gdip_Startup()
pBitmap:=Gdip_CreateBitmapFromHBITMAP(hbmp)
Gdip_GetDimensions(pBitmap,w,h)
nPixels:=w*h
ctr:=0
t1:=A_TickCount
Loop, % h {
	y:=A_Index-1
	Loop, % w {
		x:=A_Index-1
		argb:=Gdip_GetPixel(pBitmap, x, y)	
		; get
		Gdip_FromARGB(argb, a, r, g, b)		; a,r,g,b byref
		; transform
		hsl:=HSL_Convert2HSL(r/255,g/255,b/255)
		rgb:=HSL_Convert2RGB((h:=hsl.h*factor_h)>1?1:h, (s:=hsl.s*factor_s)>1?1:s, (l:=hsl.l*factor_l)>1?1:l)	
		argb:=Gdip_ToARGB(a, rgb.r*255, rgb.g*255, rgb.b*255)					
		; Set
		Gdip_SetPixel(pBitmap, x, y, argb)
		ctr++
		if (showProgress && !mod(ctr,updateRate))
			ToolTip, % "Progress: " round(100*ctr/nPixels,3) "% done. (" ctr " pixels of " nPixels ")`nTime elapsed: " round((A_TickCount-t1)/1000) "s."
	}
	
}
ToolTip, done
hbmp_out:=Gdip_CreateHBITMAPFromBitmap(pBitmap)
; Preview - after
gui,add,text,ys,After:
gui, add, pic,, % "hBitmap:" hbmp_out
gui,show
Gdip_Shutdown(pToken)
sleep,1000
tooltip
return
Always test on a small version before doing the full transformation. Eg set LoadPicture("myPic.bmp", "w128 h-1"), it takes a few seconds even when this small. A full-scale image takes a few minutes.
Results
hsl_happy.png
hsl_happy.png (676.37 KiB) Viewed 1334 times
Making happy colors. Factor settings: factor_h:=1, factor_s:=1.8, factor_l:=1. Full image
hsl_cats.png
hsl_cats.png (209.54 KiB) Viewed 1334 times
Increasing the luminosity. Factor settings: factor_h:=1, factor_s:=1, factor_l:=1.4 (I think :oops: ) Full image

Image credits: Internet :roll:

Thanks for sharing, cheers!

Return to “Scripts and Functions”

Who is online

Users browsing this forum: Xtra and 30 guests