[whatwg] I believe source rectangles for HTML5 Canvas drawImage are specified incorrectly
kevin.gadd at gmail.com
Mon Dec 10 10:48:06 PST 2012
(Sorry if you get this twice. For some reason my first reply was
bounced by the listserv?)
On Mon, Dec 10, 2012 at 10:24 AM, Ian Hickson <ian at hixie.ch> wrote:
> There's two ways to do scaled sprites with drawImage(): have a border of
> transparent black around each sprite, or copy the data out of the sprite
> sheet and into a temporary canvas at its original size, then scaling from
How big does the border of transparent black have to be? Maybe I'm
reading the spec incorrectly, but given the way it's written,
implementations would be free to make use of hardware mip-maps when
rendering images, which would mean that when scaling down, values from
arbitrarily far outside the source rectangle could get pulled in.
Temporary canvases for every blit seems like it would imply a
significant performance penalty, as well, but I haven't tested that
technique - maybe it's okay. I do know that creating a large number of
temporary canvases causes performance issues in IE.
> Disabling image smoothing will increase artefacts, that's kind of the
> point. :-) Having said that, I don't really see what that test case is
> demonstrating. Can you elaborate?
If the test case is demonstrating the behavior I argue correct, the
drawn images in the canvas at the bottom will not show any red pixels.
Another arguably correct approach would be for red pixels only to
appear with image smoothing enabled. It doesn't make sense even given
the current spec for red pixels to appear when smoothing is disabled -
if you're drawing with nearest neighbor sampling, the red pixels that
appear in the current test case (in Firefox on Windows, at least) can
only be there if partial pixels are being rendered, which shouldn't be
possible using nearest neighbor.
An acceptable compromise in this case, IMO, would be to at least
require that pixels from outside the source rectangle are not read if
image smoothing is disabled.
> The reason to prefer the current behaviour is if you want to just update a
> small part of an image. For example, if you draw a bit photo, then draw
> text over it, then want to remove the text by just drawing the photo over
> where the text was but not redrawing the whole thing. If we clamped to
> source rectangle, we'd get artefacts in this case that couldn't be worked
> around (unlike the problems with scaling sprites, which can be worked
> around, albeit in a suboptimal fashion).
Using a clip seems like the right way to do that. If you want to
update a subregion, set a clip to the region to update, and run the
exact same drawing code you ran before. That would work regardless of
the semantics defined for source rectangles, and be applicable for all
drawing primitives, not just drawImage. I can see how the performance
characteristics for canvas clips might be too awful for that to be
viable, though, but in that case we're now arguing over which
applications should get the bigger performance hit. In that scenario,
I would strongly suggest that games should be the ones to get
privileged performance since they're extremely performance dependent
to begin with. I don't know what applications actually use that
behavior, though, so maybe they're just as performance focused.
More information about the whatwg