Hi, ;)

I've been busy making my own color-choosing dialog to replace the standard Windows color dialog. In the process of doing so, I wrote these two routines that do simple RGB-to-HSL and HSL-to-RGB conversion. Since it doesn't use any floating point math, it's sure to be faster (maybe?) and smaller. The disadvantage to this is slight inaccuracies. Not very big though. When I tested it against the standard floating point routine, (yes I tested it for every value, from 000000 to FFFFFF) the results were at most 1 value off - which, in the world of computer color, isn't a very noticeable difference. ;)

Comments are encouraged, and I would prefer suggestions to optimize size instead of speed. Speed is unimportant here.

Having said that, I hope this can be useful to somebody out there. Enjoy. ;)

-ib



[size=12]

RGB2HSL proc uses esi edi ebx, dwRGB:DWORD
;-- ------------------------------------------------------------;
; By Greg Hoyer aka "Iblis" ;
; ;
; RGB2HSL converts a COLORREF oriented dword filled with 8bit ;
; Red/Green/Blue values (00ggbbrr) to a similarly oriented ;
; dword filled with Hue/Saturation/Luminance values (00llsshh) ;
; This procedure returns the full range, from 0-255. This ;
; offers slightly more precision over Windows' "color picker" ;
; common dialog, which displays HSL values ranging from 0-240. ;
; ;
; It is important to note that true HSL values are normally ;
; represented as floating point fractions from 0.0 to 1.0. ;
; As such, this algorithm cannot be used to do the precise, ;
; consistent conversions that may be required by heavy-duty ;
; graphics applications. To get the decimal fraction for ;
; the returned values, convert the Hue, Saturation, and/or ;
; Luminance values to floating point, and then divide by 255. ;
;--------------------------------------------------------------;
movzx esi, byte ptr [dwRGB+2]
movzx edi, byte ptr [dwRGB+1]
movzx ebx, byte ptr [dwRGB+0]
mov cl, -1
cmp esi, edi
ja @cmp1
xchg esi, edi
neg cl
shl cl, 1
@cmp1: cmp edi, ebx
jb @cmp2
xchg edi, ebx
neg cl
@cmp2: cmp esi, ebx
ja @cmp3
xchg esi, ebx
not cl
@cmp3: neg ebx
add ebx, esi
mov eax, edi
add edi, esi
jz @done
sub esi, eax
jz @done
mov eax, esi
shl eax, 8
sub eax, esi
push edi
cmp edi, 0FFh
jbe @csat
neg edi
add edi, 510
@csat: xor edx, edx
div edi
pop edi
shr edi, 1
shl eax, 8
or edi, eax
add cl, 3
jnc @noneg
neg ebx
@noneg: shl cl, 2
mov eax, 13135DB9h
shr eax, cl
and eax, 7
mul esi
add eax, ebx
mov ebx, eax
shl eax, 8
sub eax, ebx
mov ebx, esi
shl esi, 1
lea ebx, [ebx*4+esi]
xor edx, edx
div ebx
shl eax, 16
or eax, edi
@done: bswap eax
shr eax, 8
ret

RGB2HSL endp



HSL2RGB proc uses esi edi ebx, dwHSL:DWORD
;--------------------------------------------------------------;
; By Greg Hoyer aka "Iblis" ;
; ;
; HSL2RGB does the opposite of RGB2HSL. It converts a ;
; Hue/Saturation/Luminance (00llsshh) dword back into its ;
; corresponding RGB COLORREF (00bbggrr). This function is ;
; intented to be used exclusively with RGB2HSL (see above) ;
; ;
; If you're using this for your own custom color-chooser ;
; dialog, remember that the values are in the range of 0-255. ;
; If you MUST emulate the Windows' color-chooser, convert HSL ;
; values this way before you display them: ;
; ;
; display_value = ( x * 240 ) / 255 ;
; ;
; ...where x represents any one of the HSL values. ;
;--------------------------------------------------------------;

movzx ebx, byte ptr [dwHSL+2]
lea esi, [ebx*2]
movzx edi, byte ptr [dwHSL+1]
xor eax, eax
mov cl, 1
cmp bl, 7Fh
ja @lcase
dec al
xor ecx, ecx
@lcase: add eax, edi
mul ebx
or ecx, ecx
jz @scase
neg eax
add eax, ebx
add eax, edi
@scase: xor edx, edx
xor ecx, ecx
dec cl
mov edi, ecx
div ecx
jz @done
mov ecx, eax
sub esi, eax
movzx eax, byte ptr [dwHSL+0]
mov ebx, eax
shl eax, 1
lea eax, [ebx*4+eax]
xor edx, edx
div edi
mov ebx, eax
mov eax, ecx
sub eax, esi
mul edx
push ebx
mov ebx, ecx
shl ebx, 8
sub ebx, ecx
sub ebx, eax
xchg eax, ebx
xor edx, edx
div edi
shl eax, 24
or ecx, eax
mov eax, esi
shl eax, 8
sub eax, esi
shl esi, 16
or ecx, esi
add eax, ebx
xor edx, edx
div edi
mov ch, al
mov eax, ecx
pop ecx
cmp cl, 6
jz @done
or ecx, ecx
jz @done
bswap eax
rol eax, 8
xchg ah, al
dec ecx
jz @done
ror eax, 8
xchg ah, al
dec ecx
jz @done
rol eax, 8
xchg ah, al
dec ecx
jz @done
bswap eax
rol eax, 8
xchg ah, al
dec ecx
jz @done
ror eax, 8
xchg ah, al
@done: and eax, 0FFFFFFh
ret

HSL2RGB endp
[/size]
Posted on 2002-08-18 13:51:05 by iblis
Nice :alright:
Posted on 2002-08-18 19:10:54 by comrade
Oops :(

I relentlessly tested the first algo but it seems that I neglected the second one. Please adjust the code between @scase and @lcase in HSL2RGB() to this:

[size=12]

@lcase: add eax, edi
mul ebx
or ecx, ecx
jz _scase
neg eax
mov ecx, ebx
add ecx, edi
mov edx, ecx
shl ecx, 8
sub ecx, edx
add eax, ecx
@scase: xor edx, edx
[/size]


Sorry. :/
Posted on 2002-08-19 15:19:31 by iblis
Hi !

Nice work !

May I implement it into the next release of the X-Filez ?


Greetings, Caleb
Posted on 2002-08-19 17:09:49 by Caleb
Nice algo, I was going to implement one for my color picker but never got around to it. Also wanted to do CMYK. If you want to see what I've done previously, Check out my post. Maybe it can save you some time, or give you new ideas.
Posted on 2002-08-19 23:08:32 by CsnWltr
Thanks all,



Caleb,
I don't know what X-Filez is, but yes you may use it however you wish. That's why I made this post, to share.


CsnWltr,

I checked out your color picker and it's very nice! :alright: I especially like how the gradient fills of the slider bars change with each value. The color picker I'm currently making will be ultimately used for an art program (thus the need for HSL and CMYK) I am going to need more functionality, but I thank you for your input and ideas.



Also wanted to do CMYK.


I didn't post my CMYK routines because I didn't think anybody would care. Maybe I am wrong. Here they are.


[size=12]RGB2CMYK proc dwRGB:DWORD

;--------------------------------------------------------------;
; By Greg Hoyer aka "Iblis" ;
; ;
; RGB2CMYK converts a COLORREF oriented RGB value (00bbggrr) ;
; to a similarly oriented CMYK value. (kkyymmcc) ;
; Black color adjustment is performed automatically. ;
;--------------------------------------------------------------;

mov ecx, dword ptr [dwRGB+4]
not ecx
mov edx, ecx
bswap ecx
mov cl, ch
cmp cl, dl
jb @cmp1
mov cl, dl
@cmp1: cmp cl, dh
jb @cmp2
mov cl, dh
@cmp2: mov eax, ecx
or al, al
jz @done
mov edx, 0x01010101
movzx eax, cl
mul edx
xor al, al
xchg eax, ecx
sub eax, ecx
@done: bswap eax
ret

RGB2CMYK endp

; ################################################################

CMYK2RGB proc dwCMYK:DWORD
;--------------------------------------------------------------;
; By Greg Hoyer aka "Iblis" ;
; ;
; CMYK2RGB converts a reverse oriented CMYK value (kkyymmcc) ;
; to a COLORREF oriented RGB value. (00bbggrr) ;
;--------------------------------------------------------------;

mov eax, dword ptr [esp+4]
rol eax, 16
xor ecx, ecx
mov ch, ah
mov edx, ecx
mov cl, 3
@jmp1: mov dl, -1
add al, ch
jnc @jmp2
mov dl, al
@jmp2: dec cl
jz @done
rol eax, 8
shl edx, 8
jmp @jmp1
@done: xor eax, edx
ret

CMYK2RGB endp[/size]
Posted on 2002-08-20 04:15:03 by iblis
Thanks ! It could be useful for the D3DColor include.

The name X-Filez is the (new) working title of the direct-x-includes. This sounds better ;)

I want to free it from the oaidl.inc include because this one isn't freeware ( :mad: )

Greetings, Caleb
Posted on 2002-08-20 14:09:00 by Caleb
jz _scase

Typo? Must have been:
jz @scase
Posted on 2003-03-16 14:21:31 by The Svin
Yes, typo. But I couldn't edited it.
Posted on 2003-03-18 21:06:08 by iblis
Please post updated/corrected code.

Thanks, P1
Posted on 2003-03-19 09:25:05 by Pone
Iblis

For my curiosity, could you direct me to where I could find the information (formulas) indicating how to convert from RGB to HSL and vice-versa.

Raymond
Posted on 2003-03-19 10:29:04 by Raymond
bitRake gave a very good link in "Light and Shadow" thread Main forum.
iblis, you could ask Hiroshimator to edit it.
Posted on 2003-03-19 15:03:54 by The Svin
Here's the full working source for all four procs,

Attachment:
Posted on 2003-03-19 15:41:25 by iblis