Description
Instead of creating an RGBA ImageData object and calling putImageData, it would be faster to store pixels directly onto the canvas. Copying is pretty fast + cheap, but not free by any means.
Or for another use-case, I want to draw some text + xy axes on a canvas with some existing pure-JS code, then copy those pixels to an indexed image format (uint8_t pixels + a palette), using native code with AVX2 SIMD, mapping alpha=0 to 0 and alpha=255 to 1. (Then I use another part of that array as uint8_t histogram bins, generate an appropriate palette, and feed it to a PNG encoder. If we were writing this from scratch now, we might use a different graphics library with good support for indexed images, but this is the path of least resistance).
canvas.ToBuffer("raw")
makes a copy, instead of returning an ArrayBuffer reference to the actual underlying canvas->surface()
or something. The interesting pixels are in a small known area of the canvas, so that's a huge amount of wasted work (and cache footprint).
Ideally there'd be an API with even more room for shooting yourself in the foot that lets you read/write the canvas surface directly. Or maybe just read but not write, if JS can enforce that for a zero-copy reference. (I barely know JS; in C++ you'd do this by returning a const uint32_t*
which lets the caller break things by casting away the const
, but only if they do it on purpose).
If zero-copy isn't feasible or desirable, maybe we can have an API for efficiently copying just some selected parts of the canvas so I can copy just the left and bottom edges (into two separate rectangles)?
getImageData
can copy, but it has to format-convert and undo the premultiplied alpha. The current implementation is also much slower than necessary (#909), but it still can't be as fast as just copying. Especially for the special case of dst width = the full canvas width, so a single memcpy can get all the requested rows.
For my use-case, I'd be happy with a C++-only API. I mostly want to get at the raw pixels with native code anyway.