[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)
> (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
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