[Pixman] sRGB processing for pixman

Antti S. Lankila alankila at bel.fi
Sun Jun 10 02:51:34 PDT 2012

On 10.06.2012 06:46, Bill Spitzak wrote:
> A problem with sRGB for line art is that drawing an inverted drawing 
> will not look correct to users. White lines and text will look much 
> too thin, while black lines and text look thicker. This appears to be 
> because humans invert images in perceptual space. It is possible this 
> could be compensated for by adjusting font weights and line widths 
> depending on the current fg/bg colors so they always look perceptually 
> the same thickness.

This is a physiological problem that I'd like to declare out of scope 
for this implementation. I am aware -- thanks to you -- that white 
colors seem to bleed over blacks somewhere in the human visual system, 
but I do not realistically know what I could do about it.

Nevertheless, people who render with sRGB compositing presumably will 
tune the result towards whatever looks right for them, maybe using 
thinner line strokes when they judge something too heavy; without any 
sRGB surface they have much harder time doing high-quality results in 
the first place because of the jaggedness of fine line renderings that 
result from the messed up gamma. So sRGB is still *extremely* useful 
even if we ignore this problem, I think.

> I have never seen images stored as described in the paper. In all 
> cases the red is multiplied by whatever number is in the file for the 
> alpha. So if "red" and "alpha" are the true linear values, the file 
> either has this:
>     red^(1/2.2)*alpha, alpha (probably more common)
> or:
>     (red * alpha)^(1/2.2), alpha^(1/2.2)
> The paper appears to describe:
>     (red * alpha)^(1/2.2), alpha

The first format is out because it makes the conversion to linear color 
space hardest to do: the alpha has to be divided out, then you look up 
component value from a table, then you multiply back with alpha. This 
makes it a poor choice for a texture format.

Alpha is in general understood to be a linear blending value from 0 to 
1. We could make it nonlinear if we want, it's just one more table 
lookup to do; the question is most likely best resolved by pondering 
whether nonlinear alphas are easy for other people to generate or 
accept, as pixman's primary point is to be useful to other people. At 
least I've never heard of anyone suggesting that alpha should be 
nonlinear for increasing the range of the expressible blends, so there's 
probably no demand for nonlinear alpha. Also, the sRGB texture format 
extension defined alphas to be linear.

So the last format is the one ssp and I chose because it represents the 
least amount of work within pixman implementation, but I grant that it 
requires somewhat more explaining before it is clear to library users. 
However, people who understand the processing pipeline probably agree 
that premultiplied alphas make most sense, and gamma just adds another 
twist to it, one which is not very onerous to handle. (I return to this 
topic at end of this mail.)

> Estimating the gamma as 2 is easily close enough considering all the 
> other unknowns and the fact that data has been rounded to 8 bits, and 
> it does make the resulting compositing functions much simpler so they 
> can be done without lookup tables.

Correctness arguments are important too. Not everyone has displays with 
0.2 gamma errors, so IMHO we should do as good job as we can, within 
some reasonable limits. If one desires to use 2 as the gamma to 
approximate sRGB, that is easy to linearize as it's just squaring of the 
8-bit integer component. However, the reverse requires an integer sqrt, 
and these algorithms all seem to use integer division which is not 
available on many ARM CPUs, for instance.

The tables are quite small: 512 bytes (256 values) for sRGB -> linear 
conversion, and 4096 bytes (4096 values) for the reverse computation. 
The latter table should actually be 65536 elements long if we wanted to 
do the full 16-bit precision conversion back, but as I saw long runs of 
0,0,0,0, 1,1,1, etc. in the table, I decided to trade precision for CPU 
cache efficiency. The table still generates every sRGB component value 
from 0 to 255, but it might occasionally round the value down incorrectly.

> OpenGL also supports sRGB compositing, and exactly how it does it 
> should be investigated and copied if it makes any sense, since only 
> that way could Cairo use it for acceleration on a gl backend.

I believe the sRGB texture format paper said something about the 
conversion being most likely tabled in hardware, so I'm going to guess 
they actually do "exact" sRGB. But of course, I do not know and the 
question might have to be resolved empirically by constructing test 
cases for hardware to perform and modeling the result manually. In any 
case, we should most likely start form the assumption that the 
conversion is actually sRGB as stated in the standard, unless someone 
can prove something different.

I do want to point out one advantage of using, say gamma=2.2 in lieu of 
the actual sRGB formulas in some situations: exponentiation permits 
separate treatment of alpha and color components. For instance

(component * alpha)^2.2

is just

component^2.2 * alpha^2.2

and this comes into play when library users read in, say, PNG, and see 
some alpha values and prepare that texture for pixman. In the past, they 
would have multiplied the components by alpha (I imagine), but now they 
must only raise the alpha to 2.2 first before the texture is ready for 
consumption by pixman. However, full sRGB formula requires:

lin2srgb(srgb2lin(c) * a)

which will be far more work to implement, and the results aren't going 
to be any different in practice.


More information about the Pixman mailing list