2

I'm working in Haskell with gtk2hs, and have come across a problem I can't find an answer to.

I am writing a very simple program: it takes a colour value (or multiple colour values), and then will apply a function to them. It can do things like complementary colours, the mean of a set of colours, and so on. I've finished putting the interface together in Glade, and have read a few simple tutorials on using gtk2hs; everything works so far, and my interface will show up when I run my program.

However, my problem is with the ColorSelection widget. When I get my value from it, the value it gives is of the type Color Word16 Word16 Word16, where each Word16 is between 0 and 65535. What I want to be able to do is to convert that into a Hex triplet (as a String) ideally, or something that I can convert into a Hex triplet. So far, I've found out that it seems to be something to do with the fact that colours are stored as rrrrggggbbbb, rather than the HTML-style rrggbb. What I've found, using this code:

colorToHex (Color a b c)
    =  (showHex a "") ++ " " ++ (showHex b "") ++ " " ++ (showHex c "")

is that, although most of the time it's accurate, when using the colour picker tool I can input a colour that seems different to what is output. For example, using the colour picker, I selected #A9D06E - however, my function returned "aa11 d12d 6e41". Although fairly close, I can't work out the relationship - how does the rounding for the red channel work in this example? Also, if I type the hex value #A9D06E directly, I get "a9a9 d0d0 6e6e".

I have tried using Hoogle to find a function which converted a Colour to a String, or a Colour to anything else, and have searched the documents on Hackage for the Gtk package, but did not find anything there that would do what I wanted. I have also searched the internet, and could not find much about dealing with the Colour type. I did find one function for doing exactly what I wanted, located at the bottom here. However, this had the same problem, in that it wouldn't give the same value as the colour picker itself gave for a particular selection.

Update 1

I have also tried bitshifting the values. Shifting by 8 bits almost always gives the right value, but, as per the other things I tried, every so often it is slightly out.

1 Answers1

1

I think I've found the answer to my own question here - after a bit of digging, I've found that what I want to do is convert what the GTK colour picker gave me - that is, a 16 bits-per-channel colour - into an 8 bpc colour. Armed with that, I found this page on the Adobe forums. Using the answer posted there, I wrote some Haskell code which will convert a value of type Color into a Hex triplet, and seems, as far as I've found, to always match up with the value reported on the colour picker itself. Here's the code I'm using:

toHex :: (Integral a, Show a) => a -> String
toHex i
  | length o == 1 = '0':o
  | otherwise     = o
  where
    o = map toUpper $ showHex i ""

d16to8 :: Integral a => a -> Integer
d16to8 i = (255 * d16to15 + 16385) `div` 32768
  where d16to15 =  (32768 * (toInteger i) + 32768) `div` 65535

colorToHex :: Color -> String
colorToHex (Color a b c) = (toHex.d16to8 $ a) ++ (toHex.d16to8 $ b) ++ (toHex.d16to8 $ c)