Gamma-corrected alpha blending for text output
Submitted by Antti S. Lankila
Assigned to David Turner
Description
I'm soliciting interest for improving text rendering on the Linux desktop by applying gamma correction for the text. I have written a couple of JavaScript demos (for use in chromium or firefox) that can demonstrate the problem and what I think should be done about it.
To view these demos, a TFT display with RGB subpixel order is required. Chromium is preferred because of faster JavaScript execution. I have not tested the demo on other browsers.
Firstly, a screenshot highlighting the difference between Linux and Windows 7 font rendering. The gnome font settings are set to 'no hinting', and LCD with RGB subpixel order. I've also installed the msttcorefonts to have the Arial font used on the demo:
http://bel.fi/~alankila/lcd/lcd.png
The Linux browser's rendering on the bottom left shows a dirty halo around the text on black-on-white, clear color fringing on white-on-black, and significant darkening of the green-on-violet test cases. In summary, the javascript results are similar on both linux and windows, and the windows 7 output resembles the javascript output much more than linux output. Subjectively, the linux results are far worse than the others.
The actual demo can be played with here:
The demo renders the text anew on changes to text field input value. For instance, replacing the gamma 2.0 value with neutral gamma 1.0 produces javascript results that are distinctly similar to those given by linux browsers. Therefore it seems likely that lacking gamma correction on text output is the reason for the poor results on Linux.
As additional evidence, executing "xgamma -gamma 2.0" makes the Linux browser results seem fairly similar as the javascript results are with normal gamma value, indicating that Linux font rendering can be remedied by use of linear gamma display.
From this, it is fair to conclude that the key problem is the assumption that alpha blending can be performed as linear blend between color values in sRGB space. This is only true if the sRGB space maps linearly to physical intensity ("screen space") of the pixel on the display surface, in other words, only when gamma is 1.0. When it is not 1.0, it is necessary to raise the color component to the gamma, then perform blending linearly, and then raise to 1/gamma to get back to sRGB space.
Typical monitors use gamma values from 1.8 to 2.2, and therefore all alpha blending operations should, in principle, compensate for gamma. However, that may be unacceptably slow, so a compromise might be to fix only text, where this problem matters most. In addition, the difference between 1.8 or 2.2 to 2.0 is not very large, indicating that it may be acceptable to treat the gamma value as fixed constant, rather than user-specified variable.
To demonstrate the screen space alpha blending, I have made another page which works as a measuring tool for display system's gamma value:
http://bel.fi/~alankila/lcd/gamma.html
it is based on the color blending idea which is used on the LCD test page to show how fonts can be put on screen without color fringing artifacts. For instance, on the leftmost blocks calibrated for gamma 2.0, the middle square is 0xb4b4b4 in color. This is because the light intensity midpoint between 0x000 and 0xfff is not 0x888, but it is actually given by:
desired_intensity^(1/gamma) = 0.5^(1/2.0) = 0.707,
which mapped to 0 .. 255 range gives 0.707 * 255 = 0xb4.
This provides the clue to understanding why Linux results on the green-on-violet text seem much too dark. The combination of 0xf0f and 0x0f0 tends to produce the value 0x888 when gamma is being ignored, but it is much too dark. The same problem is responsible for the color fringing in the other cases as well, of course.
Version: 1.9.9