[whatwg] More ImageData issues

On 22/02/2008, Oliver Hunt <oliver at apple.com> wrote:
>  At the moment the spec merely states that
> putImageData(getImageData(sx,sy,..),sx,sy) should not
> result in any visible change to the canvas, however for those
> implementations that use a premultiplied buffer there is a necessary
> premultiplication stage during blitting that results in a loss of precision
> in some circumstances -- the most obvious being the case of alpha == 0, but
> many other cases exist, eg. (254, 254, 254, alpha < 255).  This loss of
> precision has no actual effect on the visible output, but does mean that in
> the following case:
>  imageData = context.getImageData(0,0,...);
>  imageData.data[0]=254;
>  imageData.data[1]=254;
>  imageData.data[2]=254;
>  imageData.data[3]=1;
>  context.putImageData(imageData,0,0);
>  imageData2.data = context.getImageData(0,0,...);
>
>  At this point implementations that use premultiplied buffers can't
> guarantee imageData.data[0] == imageData2.data[0]
>
>  Currently no UA can guarantee a roundtrip so i would suggest the spec be
> updated to state that implementations do not have to guarantee a roundtrip
> for any pixel where alpha < 255.

The spec does not state that getImageData(putImageData(data)) == data,
which is where the problem would occur. It only states that
putImageData(getImageData) == identity function, which is not a
problem for premultiplied implementations (since the conversion from
premultiplied to non-premultiplied is lossless and reversible). So I
don't think the spec needs to change at all (except that it could have
a note mentioning the issue).

(getImageData can convert internal premultiplied (pr,pg,pb,a) into
ImageData's (r,g,b,a):

    if (a == 0) {
        r = g = b = 0;
    } else {
        r = (pr * 255) / a;
        g = (pg * 255) / a;
        b = (pb * 255) / a;
    }

(using round-to-zero integer division). putImageData can convert the other way:

    pr = (r*a + 254) / 255;
    pg = (g*a + 254) / 255;
    pb = (b*a + 254) / 255;

Then put(get()) has no effect on the values in the premultiplied buffer.)

-- 
Philip Taylor
excors at gmail.com

Received on Tuesday, 29 April 2008 18:31:07 UTC