python-imaging/Pillow — pull request #159 by homm (2013-03-24 22:19:29+00:00)
Title: Precision of alpha composite. Again.

I rewrite math again. And now I can definitely say: this is best 32 bit alpha composite implementation :) (or one of).

I tested it hardcore. This is how I get test case:

def prepare_test_images(dim):
"""Plese, be careful with dim > 32. Result image is have dim ** 4 pixels
(i.e. 1Mpx for 32 dim or 4Gpx for 256 dim).
"""
i1 = bytearray(dim ** 4 * 2)
i2 = bytearray(dim ** 4 * 2)
res = 255.0 / (dim - 1)
rangedim = range(dim)
pos = 0
for l1 in rangedim:
for l2 in rangedim:
for a1 in rangedim:
for a2 in rangedim:
i1[pos] = int(res * l1)
i1[pos + 1] = int(res * a1)
i2[pos] = int(res * l2)
i2[pos + 1] = int(res * a2)
pos += 2
print '%s of %s' % (l1, dim)

i1 = Image.frombytes('LA', (dim ** 2, dim ** 2), bytes(i1))
i2 = Image.frombytes('LA', (dim ** 2, dim ** 2), bytes(i2))
return i1.convert('RGBA'), i2.convert('RGBA')

im1, im2 = prepare_test_images(63)
im1.save('im1.png')
im2.save('im2.png')

I.e this is two images with 3969×3969 pixels size. This is almost 16 millions test cases! I let @twpayne's implementation as reference and write the script to control differences: https://gist.github.com/homm/5233715 This script write files with visual differences and print to stdout statistic.

For my previous implementation statistic is:

red 126: 458712 127: 15285424 128: 8825
grn 126: 458712 127: 15285424 128: 8825
blu 126: 458712 127: 15285424 128: 8825
alp 126: 527877 127: 15225084

This mean about 3% of data channels and 3.4% of alpha channel has difference in one value. And compositing took ≈570ms.

For implementation in this PR stats are:

red 126: 57273 127: 15694825 128: 863
grn 126: 57273 127: 15694825 128: 863
blu 126: 57273 127: 15694825 128: 863
alp 127: 15752961

Alpha channel have no differences by design. There is no places where alpha computation loose precisions. And only 0.37% of data channels have difference in one point. Also this implementation done in ≈490ms.