[Pixman] Proposal for pixman's glyph rendering: alpha correction

Antti Lankila alankila at bel.fi
Fri Mar 15 05:56:09 PDT 2013


Behdad Esfahbod <behdad at behdad.org> kirjoitti 15.3.2013 kello 10.30:

> On 13-03-13 09:59 AM, Antti Lankila wrote:
>> I have a suggestion for getting sRGB-like text rendering without having sRGB alpha blending primitive. It's based on adjusting the alpha values of the glyph masks based on text foreground color without knowledge of the background color. I generated a writeup of it here:
>> 
>> https://bel.fi/alankila/lcd/alpcor.html
>> 
>> This looks like something that pixman's new glyph rendering code might consider doing. Thoughts?
> 
> Hi Antti,
> 
> This is indeed interesting, and very similar to what Skia does.  I believe
> Skia has five buckets for the alpha, and ignores the middle bucket.

Hmm. I am looking at skia's source now -- and I find code that looks very familiar. They basically have the same theory about alpha correction in SkFontHost_FreeType.cpp, though there's also a function called apply_contrast which I do not quite understand at this point of time. Basically it looks like a nonlinear correction to alpha which is folded into the gamma tables. Otherwise the parallels are quite strong.

static void build_gamma_table(uint8_t table[256], int srcI) {
    const float src = (float)srcI / 255.0f;
    const float linSrc = lin(src); /* sRGB to linear */
    const float linDst = 1.0f - linSrc; /* note: same assumption for background as I make */
    const float dst = per(linDst); /* linear to sRGB */

After this point, follows selection of contrast value between 0 .. 0.4, for which I have no equivalent:

    const float contrast = SK_GAMMA_CONTRAST / 255.0f * linDst; /* = 0.4f * linDst */

And this value is used to manipulate the input alpha before it is passed into the usual linear alpha blending compensation: calculate what the right sRGB-blended result should be, then solve for the alpha that gives that result. The contrast defined here is used as input for this function:

static float apply_contrast(float srca, float contrast) {
    return srca + ((1.0f - srca) * contrast * srca);
}

It is evident that this function is identity if contrast is set to zero, and if contrast were 1, it replaces srca by:

   srca + (1.0f - srca) * srca
   <=> -srca ** 2 + 2 * srca

which is evidently an upside down parabola with zero derivate occurring at srca=1, and it passes through points (0, 0) and (1, 1), so this function has the effect of artificially increasing the alpha value somewhat, or making the text stronger when the background is light. With the 0.4 contrast parameter, the correction is maximally approximately 0.1 alpha units, so I guess it is compensating for eye's tendency to bleed white areas into darker areas which makes black-on-white text appear unusually narrow. In other words, it's probably a perception hack.

Skia prepares 4 discrete alpha correction tables for foreground values 0x00, 0x55, 0xaa and 0xff. These are selected between through using the top 2 bits of the foreground color component value. The processing is per-component as can be expected.

> That said, it resulted in really bad color fringing in bright-on-black text in
> Chromium.  I'll try to find the bug.  But then, Skia is doing a lot more stuff
> with the glyph masks, so I wouldn't be surprised if it was a Skia screwup.

It is possible. The technology itself should be able to handle these color combinations without generating an intrinsic error in the process. Skia can be built with different options, so perhaps yours was not using the full component alpha correction?

> Do you have before / after images?

I took a few screenshots of epiphany (corrected) against firefox. Though I think form elements in firefox appear corrected too though regular text is rendered the usual way.

https://bel.fi/alankila/epiphany-vs-firefox.png
https://bel.fi/alankila/epiphany-vs-firefox2.png

When viewing screenshots, please ensure they are viewed in 1:1 scaling.

-- 
Antti

-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/pkcs7-signature
Size: 2748 bytes
Desc: not available
URL: <http://lists.freedesktop.org/archives/pixman/attachments/20130315/1a9cee41/attachment.bin>


More information about the Pixman mailing list