[reportlab-users] HexColor()

Lalo Martins reportlab-users@reportlab.com
Thu, 13 Feb 2003 19:02:24 -0200


For my current project, I had to write a function similar to HexColor which
can accept both RGB and CMYK.  So I went to read the source, and I found it,
forgive me for the bluntness, rather nonsensical.

Why does a functin named *Hex*Color accept a decimal?

Why does it do the dreaded 'if type(val) == StringType' test, which means it
will break if I pass it an Unicode or a custom object that behaves like a
string?  This is very un-pythonic, and I can't see an use case for passing
in a numeric argument (but if there is one, then it would have to be served
by a different function).

Don't get me wrong, I like the overall quality of the code a lot - this
function just does't match ;-) I'll assume it is a relic of organic
evolution, and less enlightened times.

One additional feature my customer wanted is that it allows any "width" for
each color, so "f90" and "f09000" and "f00900000" are equivalent.  This
introduces, however, a small ambiguity - should "ABCDEFGHIJKL" be
interpreted as rgb(ABCD,EFGH,IJKL) or cmyk(ABC,DEF,GHI,JKL)?  I decided this
isn't important enough; my code would interpret it as cmyk, since I guess 4
hex digits is much more precision than I care about in my colors (and if you
need it, please go instantiate the colors yourself instead of using hex!)

Here is the version I'm using:


def HexColor(val):
	"""This function converts a hex string into the corresponding
	color.  E.g., in "AABBCC" or 0xAABBCC, AA is the red, BB is
	the green, and CC is the blue (00-FF).  In "AABBCCDD", AA is
	cyan, BB is magenta, CC yellow, DD black.

	HTML uses a hex string with a preceding hash; if this is present,
	it is stripped off.  (AR, 3-3-2000)
	"""

        if val[:1] == '#':
            val = val[1:]
        elif val[:2].lower() == '0x':
            val = val[2:]
        l = len(val)
        if (l%4) == 0:
            # cmyk
            w = l/4
            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)
            return colors.CMYKColor(c/scale, m/scale, y/scale, k/scale)
        if (l%3) == 0:
            # rgb
            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)
            return colors.Color(r/scale, g/scale, b/scale)
        raise ValueError, "unknown hex color format"

this code is hereby donated to the public domain.

[]s,
                                               |alo
                                               +----
--
            Those who trade freedom for security
               lose both and deserve neither.
--
http://www.laranja.org/                mailto:lalo@laranja.org
         pgp key: http://www.laranja.org/pessoal/pgp

Eu jogo RPG! (I play RPG)         http://www.eujogorpg.com.br/
GNU: never give up freedom                 http://www.gnu.org/