[reportlab-users] HexColor()

Magnus Lycka reportlab-users@reportlab.com
Tue, 18 Feb 2003 15:29:37 +0100


At 03:33 2003-02-18 -0500, reportlab-users-request@reportlab.com wrote:
>Ok, this is broken :-) Magnus pointed out that the current implementation
>divides by 256 and not 0x100

No, it's not your day today Lalo. Last time I counted 256 == 0x100! ;)

I pointed out that the code in ReportLab divides by 255.0. Right?

Now Lalo's code is fixed so that it does the same as the original
ReportLab code in the case of 8 bit strings (#AABBCC), but it can
also handle #ABC and #AAAABBBBCCCC etc.

Ok?

But I wonder... have you really tested this properly?
Just looking at the code, I see some odd things:

>         if val[:1] == '#':
>             val = val[1:]
>         elif val[:2].lower() == '0x':
>             val = val[2:]
>         l = len(val)
>         if (l%4) == 0:
>             # cmyk

Ok, so #AAABBBCCCDDD must be a CMYK string since
12 % 4 == 0

>             w = l/4

Unless you use "from __future__ import division" this will mean
that w == 0 since len returns an int. int/int => int.
w = l/4. is better. int / float => float.

>             c = int(val[:w], 0x10)
>             m = int(val[w:w*2], 0x10)
>             y = int(val[w*2:w*3], 0x10)
>             k = int(val[w*3:], 0x10)
>             scale = float(0x10 ** w) - 1
>             return colors.CMYKColor(c/scale, m/scale, y/scale, k/scale)
>         if (l%3) == 0:
>             # rgb

But if we want to use 16 bits per colour, it will be 12 characters
long, as in #AAAABBBBCCCC, and it will be interpreted as a 12 bit
CMYK colour (AAA, ABB, BBC, CCC). See above. :(

I don't think you can allow variable width if you want to accept
both CMYK and RGB colors without a flag. Personally, the only time
I write colors like #something, it's 256 bit RGB color...which is
what the original function did... Also, import this and think about
"In the face of ambiguity, refuse the temptation to guess." and
"Explicit is better than implicit.".

It's probably better to make this into two functions, one to
interpret HexCMYKColor strings, and another for HexRGBColor
strings, but I don't feel a need for anything beyond what is
currently available.

>             w = l/3

As above... => w = 0. You need w = l/3.

>             r = int(val[:w], 0x10)
>             g = int(val[w:w*2], 0x10)
>             b = int(val[w*2:], 0x10)
>             scale = float(0x10 ** w) - 1
>             return colors.Color(r/scale, g/scale, b/scale)
>         raise ValueError, "unknown hex color format"




-- 
Magnus Lycka, Thinkware AB
Alvans vag 99, SE-907 50 UMEA, SWEDEN
phone: int+46 70 582 80 65, fax: int+46 70 612 80 65
http://www.thinkware.se/  mailto:magnus@thinkware.se