# [Pixman] sRGB processing for pixman

Bill Spitzak spitzak at gmail.com
Thu Jun 21 12:57:58 PDT 2012

```Søren Sandmann wrote:

> For the 8 bpc fetcher converting from 8 bit srgb to 8 bit linear loses a
> lott of information, which is why the format is considered wide. But if
> it somehow ends up being used with the 8 bit pipe (and currently it
> will, because at the moment everything with a transformation ignores the
> wide path), the pixels still need to be linear. We may need a 256->256
> table doing 8-bit sRGB to 8-bit linear.

Error diffusion helps a lot with these conversions, and actually makes
8-bit linear *somewhat* useful. With this a smooth sRGB gradient
converted to 8-bit linear and then back is noisy but looks much better
than the severe banding you would get with just an 8-bit lookup table.

In my experience there is no need for complex pattern error diffusion.
Instead all the error is dumped into the next pixel. This would fit with
your fetchers that do only one line at a time.

In both directions, there is a 256-entry table of 16-bit numbers, which
is the conversion to the destination value in 8.8 fixed-point (thus the
largest number is 0xFF00, not 0xFFFF!).

Pick a pseudo-random point in the middle of the row and proceed like
this (either wrap around or go backwards from that point as well):

short table[256] = {...};
unsigned short error = 127;
for (;;) {
error += table[next_pixel()];
output(error>>8);
error &= 255;
}

Similar diffusion is also useful for converting floating point to 8-bit
so that smooth gradients remain smooth-looking. I used lookup tables
based on the top 16 bits of the floating point number but this was for
Irix 20 years ago and I believe on modern machines it is faster to just
do the math directly, or some polynominal approximation.

A problem is the pseudo-random starting point. This is necessary so that
you do not get vertical stripes when the rows have the same data. But if
you want your composites to not change, it has to be deterministic. I'm
not sure but perhaps a hash of the y coordinate of the source will work,
or that hash plus the color of a pixel at x==0.
```