New issue
Advanced search Search tips

Issue 1187 link

Starred by 7 users

Issue metadata

Status: New
Area: Font
NextAction: ----
Priority: Low
Type: Idea

Sign in to add a comment

Enhancement for alpha correction and LCD filtering

Reported by, Mar 25 2013

Issue description

I noticed that Skia calculates alpha correction table in SkFont_FreeType.c as follows:

static void build_gamma_table(uint8_t table[256], int srcI) {
    const float src = (float)srcI / 255.0f;
    const float linSrc = lin(src);
    const float linDst = 1.0f - linSrc;

The objective of the calculation here produces a table for replacing the source alpha value with a corrected alpha value for improving blending result when text is drawn using the component color srcI. The calculation for linDst makes the assumption that the background component is the inverse of the foreground component, and then calculates the alpha value that will produce the right blending using a linear component blend based on what the correct result of such blend would have been if sRGB aware blend had been used instead.

This technique improves the average error relative to performing a naive blend by quite a bit, and for the very important cases of white on black, and black on white, the result is in fact exact within the numerical precision. In many other cases, however, there will be some degree of error, because the background assumption is not always correct, and this tends to appear as coloration in LCD rendering.

Is the bg assumption the best possible? I submit that it is not necessary to make the assumption of dst = 1 - src: it is possible to simply approach the problem numerically and to exhaustively try every possible corrected alpha against every possible background choice for every (fg, alpha) pair, and calculate the error made relative to true sRGB blending result. The error can be measured as difference of the numerical value of the component either in linear or sRGB space, and then aggregated using typical statistical tools like root mean square or maximum error. I have chosen root mean square of component values in sRGB.

Attached, I have a couple of captures of the (fg, alpha) -> alpha_correction mapping colored with the RMS error made, showing that for a truly unknown background case -- a reasonable assumption to make for sake of generality -- the resulting blending can be significantly improved in average.

Here is a github project calculating what I expect to be the optimal mapping table: (The github project is just a fairly young prototype/reference implementation I am working on in the hopes that it might be useful for someone eventually.)

When using FreeType and LCD rendering, I also noticed that the kernel is probably not optimal. Skia appears to use FreeType's default 5-tap kernel, which appears to impart some degree of color fringing if used. The optimal 5-tap kernels should be of the following form: [a - c, a + c, 2 * a, a + c, a - c]. To generate a 1-sum kernel, a should be set to 1/6, and c is bounded to 0 <= c <= a.

This formulation produces equal excitation of all color components, and the degree of blurring can be adjusted by the freely chosen tunable c. The filter is colorless because all color components under the kernel receive a total excitation of 2*a: the central pixel is the only one of that color, so its weight is directly 2*a, and the other color pairs are weighted with a+c and a-c for total of 2*a.
153 KB View Download
149 KB View Download

Comment 1 by, Mar 25 2013

Unfortunately I wrote the wrong URL by habit. This is the alpha correction code URL I intended:
Project Member

Comment 2 by, Mar 26 2013

Project Member

Comment 3 by, Aug 26 2014

Labels: -Type-Defect Type-Idea Area-Font
Project Member

Comment 4 by, Jul 16 2015

Labels: -Priority-Medium Priority-Low
Ben, Can we get your view here... core team is clearly not getting around to it, worth low or icebox priority to keep around, okay for contributors to implement if they were so inclined?

Sign in to add a comment