[whatwg] More random comments on the putImageData definition

Oliver Hunt oliver at apple.com
Fri Jan 25 03:56:25 PST 2008


So I came across this wonderful piece of javascript:
http://jsmsxdemo.googlepages.com/jsmsx.html

If present it uses putImageData (and getImageData to get the ImageData  
object, which isn't required by html5 now -- and i think hixie was  
look at doing some more work with ImageData).

With the current model for putImageData there is no way for them to  
specify a dirty rect, which means their only option is to update the  
entire display -- they have to copy the entire buffer.  If  
putImageData were to take an optional dirty rect parameter we could  
reduce the amount of work necessary, and still maintain backwards  
compatibility.  My attention was drawn to this as a brief bit of  
hackery in webkit showed that the above webapp only updates the  
necessary dirty parts of a frame and yet Opera and Firefox both *have*  
to copy, blit and repaint the entire canvas, ironically because they  
both provide the faster get/putImageData API's (this is not to suggest  
either implementation is in any way slow, just that it seems we are  
missing a perfectly reasonable API to improve performance beyond what  
has already been achieved).

Anyway, i was thinking we would just need to putDataImage methods:
void putImageData(in ImageData imagedata, in float dx, in float dy);
void putImageData(in ImageData imagedata, in float dx, in float dy, in  
float dirtyX, in float dirtyY, in float dirtyWidth, in float  
dirtyHeight);

Where the dirtyX and dirtyY are relative to the ImageData's origin.

The repaint region would be (dx+dirtyX, dy+dirtyY),  
dirtyWidth*dirtyHeight in the canvas domain, and (more importantly)  
only that subsection of the ImageData would need to be copied, and in  
the case of those UAs that need it, unpremultiplied.  This could  
result in significant gains for more complex uses of canvas, like the  
one above.

Compatibility:
If the dirty rect is provided to a UA that doesn't support it (eg. new  
content in old/current Opera, Firefox) the entire ImageData will be  
blitted as would currently be expected (opera and firefox both ignore  
extraneous arguments on putImageData, i'm not sure about konqueror/ 
khtml).

If a dirty rect is not provided (eg. old content in a newer UA) the  
entire block would be considered dirty, and so repaint as expected.

Any thoughts?

--Oliver

On Jan 23, 2008, at 11:28 AM, Oliver Hunt wrote:

>
> On 23/01/2008, at 5:44 AM, Philip Taylor wrote:
>
>> On 23/01/2008, Oliver Hunt <oliver at apple.com> wrote:
>>> It would be great if putImageData
>>> could take a source region, in addition to the destination.  One of
>>> the primary reasons for using get/putImageData is to allow JS to
>>> rapidly blit data to the screen, however without an ability to blit
>>> only a subregion of the image data the only available options are to
>>> either re-blit the entire imagedata region (which can be expensive  
>>> due
>>> to the need for [un]premultiplying in some (all?) implementations),
>>
>> ((Opera does non-premultiplied colour internally.))
> Righto.  There's still the necessary type/range checking involved at  
> some point.
>
>>
>>> or create and populate a new ImageData object which still requires  
>>> more
>>> work than would ideally be necessary.
>>
>> You can also create a temporary canvas and putImageData once onto
>> that, and then drawImage sections onto the screen as they are needed.
>> That lets you draw lots of sections lots of times quickly (since
>> you're mostly drawing from the optimised canvas surface format, not
>> from a JS array), which perhaps helps in some (most?) of the cases.
>> (You still have to do a single putImageData of the whole data to get
>> it onto the temporary canvas, but if there are parts of the data you
>> aren't ever using then you just should make the ImageData smaller and
>> cut out the unused bits.)
>
> Yes, there are many ways you can resolve this if you're willing to  
> copy data
> around in JS, which is far less efficient than letting you use your  
> single backing
> buffer, but only (effectively) repainting part of it.
>
> Using a separate canvas also works, but still requires additional  
> copying, much more memory, and the use of drawImage which doesn't  
> have the same semantics as putImageData.
>
> --Oliver
>
>>
>> -- 
>> Philip Taylor
>> excors at gmail.com
>




More information about the whatwg mailing list