Tuesday, January 12, 2016

Playing with colour conversions

I'm posting this in case other people experience problems with using python's colorsys and can't figure out how to get values they expect.

In my tree simulation software, the graphical options allow for 2d and 3d graphical formats. When I wrote the code, I had been tinkering with CFDG a lot, so I tied into it and used it to generate the graphics. At some point I need to revisit that and use something else to generate the graphics, but here's an example of what the 2d stuff looks like.


In this case the top panel is a top down view of the simulated forest, and the bottom panel is a side view to give you an idea of what the heights look like. The relative darkness of the green colour of each canopy represents how shaded that particular canopy is. Bright green means that canopy is receiving full sunlight, and a completely black canopy would be receiving no light at all. The latter never happens since the trees die before that point.

An example 3d view looks like this.
The spherical "warts" are visually oversized propagules. This particular scene is set in Ithaca, NY at around 06:30 and the summer solstice.

CFDG uses HSV for defining colours, but the 3d output is as a dxf autocad file, meaning the colour code is use an autocad colour index (ACI). Right now the colours of propagules, canopies, and trunks are hard coded in the code that generates the dxf file, but I was working on the code so I could generate prolate spheroids for canopies, and thought I could change that so the dxf would use the come colour as the species was defined to have.

The plan was to convert HSV into RGB, and then do some colour distance maths to pick the closest ACI value. Python has a colorsys module that lets one convert RGB to/from HSV, but as I used it, it did not behave in ways I expected.

I define canopies as having a HSV colour of 117°, 100%, 100%. An online colour picker I looked at said the RGB would be 13, 255,0. Here is where the wat with colorsys began.

The colorsys module wants values input values to be between 0 and 1, and will give you corresponding values. Since "H" is HSV is in degrees, you need to take the H value and divide it by 360. Your % values get divided by 100, so you end up using 0.325, 1.0, 1.0 like:

coloursys.hsv_to_rgb(0.325,1.0,1.0)

which gives you 0.04999, 1.0, 0.0. Now you need to multiple each value of that tuple by 255 to get 12.79, 255, 0...which is close enough to 13, 255, 0.

Now I need to make a RGB to ACI lookup table that measures colour distance and picks a ACI close to the RGB given.