# [cairo] RFC: More accurate color conversion

Bill Spitzak spitzak at gmail.com
Tue Oct 8 14:59:48 PDT 2013

```I don't think there is much interest in integers with more than 16 bits.
These integers can be losslessly converted to 32-bit IEEE float even if
linearly mapped into the 0.0-1.0 range, and if any typical gamma is
applied then there are even more floating point values between the
integer conversions.

I think integers up to 22 bits can be handled losslessly, and if gamma
>= 2 is applied then 23 bits can be handled.

My main concern was that the transition of float->16->8 produce the same
result as a direct float->8 conversion. This requires that the 16 bit
values change at the same point that the 8 bit values do (otherwise two
floating point numbers that turn into different 8 bit numbers would turn
into the same 16 bit number, falsifying this requirement). I was hoping
that this would determine which conversion is better, but it turns out
both floor(x/2**n) and round(x/(2**n-1)) have matching transitions.

You do have to be careful that the float->16, float->8, and 16->8
transitions are all using matching methods.

And it is extremely important that int->float->int is the identity, iff
the int->float is lossless.

Wolfgang Draxinger wrote:

> Not if you're converting between floating point and integers. That's
> numerics 101. The numbers represented by floats are m * 2**p.
> But that can be trivially rewritten as m << p. Floating point means
> nothing else than floating shift when it comes to the binary
> representation. Which means, that for any exponent p > 0 there are 2**p
> different integers that map to the same float and that for any exponent
> p < 0 there are 2**p floating point values that map to the same integer.
>
> Your typical float has 23 bits for the mantissa and 8 bits for the
> exponent. Which means that for integer ranges [-2**23 + 1, 2**23 - 1]
> you can have a bijective mapping. Outside of that you need an exponent
> =/=0, so good luck.
```