[whatwg] Canvas context.drawImage clarification

Ian Hickson ian at hixie.ch
Mon Jul 27 15:12:18 PDT 2009


On Thu, 9 Jul 2009, Gregg Tavares wrote:
>
> The specific ambiguity I'd like to bring up has to do with the several 
> versions of a function, context.drawImage. They take width and height 
> values.  The spec does not make it clear what is supposed to happen with 
> negative values.
> 
> My personal interpretation and preference is that negative values should
> 
> (a) be legal and
> (b) draw backward, flipping the image.
> 
> The specification currently says:
> 
> "The source rectangle is the rectangle whose corners are the four points
> (sx, sy), (sx+sw, sy), (sx+sw, sy+sh), (sx, sy+sh).
> 
> ...
> 
> The destination rectangle is the rectangle whose corners are the four
> points (dx, dy), (dx+dw, dy), (dx+dw, dy+dh), (dx, dy+dh)."
> 
> Well, simple math would suggest that if sx = 10, and sw = -5 then it still
> defines a valid rectangle.

Correct. Why is this ambiguous? The rectangle is well-defined, it just 
happens that its points are given in a different order than normally.


> I'd like to make a passionate plea that the spec say "implementations 
> must support negative widths and negative heights and draw the image 
> backward effectively flipping the result".

If you want to flip the image, use a transform.


> Also, I'd like to suggest that a widths and heights of 0 for source 
> should be valid as well as rectangles outside of the source also be 
> valid and that this part of the spec.
> 
> "If the source rectangle is not entirely within the source image, or if 
> one of the sw or sh arguments is zero, the implementation must raise an 
> INDEX_SIZE_ERR exception."
> 
> be changed to reflect that.

If height or width is zero, how do you scale the bitmap up to a non-zero 
size?

We could use transparent black for the pixels outside the image, but this 
is already interoperably implemented, so I don't want to change it.


> Coming from a graphics background I see no reason why if I let my user 
> size an image in a canvas I should have to special case a width or 
> height of zero. Just draw nothing if the width or height is zero.
> Similarly, if I was to provide a UI to let a user choose part of the 
> source to copy to the dest and I let them define a rectangle on the 
> source and drag it such that all or part of it is off the source I see 
> no reason why I should have to do extra math in my application to make 
> that work when simple clipping of values in drawImage would make all 
> that extra work required by each app disappear.

I agree that this may have made sense when the API was being designed a 
few years ago.


> The next issue related to drawImage is that the spec does not specify 
> how to filter an image when scaling it. Should it use bi-linear 
> interpolation? Nearest Neighbor? Maybe that should stay implementation 
> dependent? On top of that the spec does not say what happens at the 
> edges and the different browsers are doing different things. To give you 
> an example, if you take a 2x2 pixel image and scale it to 256x256 using 
> drawImage. All the major browsers that currently support the canvas tag 
> will give you an image where the center of each pixel is around center 
> of each 128x128 corner of the 256x256 result. The area inside the area 
> defined by those 4 points is rendered very similar on all 4 browsers. 
> The area outside though, the edge, is rendered very differently. On 
> Safari, Chrome and Opera the colors of the original pixels continue to 
> be blended all the way to the edge of the 256x256 area. On Firefox 
> though, the blending happens as though the source image was actually 4x4 
> pixels instead of 2x2 where the edge pixels are all set to an RGBA value 
> of 0, 0, 0, 0. It then draws that scaled image as as though the source 
> rectangle was sx = 1, sy = 1, sw = 2, sh = 2 so that you get a 
> progressively more and more translucent color towards the edge of the 
> rectangle.
> 
> I don't know which is right but with low resolution source images the 2 
> give vastly different results.

> Here's a webpage showing the issue.
> 
> http://greggman.com/downloads/examples/canvas-test/test-01/canvas-test-01-results.html

It's not clear to me why what Firefox does is actually wrong. They use 
different assumptions, but why is it wrong? There's no trnasparency in the 
original, sure, but there's also no pixelation in the original, and no 
purple between the two pixels on the left, yet you aren't complaining 
about the introduction of pixelation or purple, both of which are done by 
one or another of the browsers.


On Thu, 9 Jul 2009, Gregg Tavares wrote:
> 
> [...] Or making it consistent when the DOCTYPE is set to something.

We're not adding any more quirks modes, four is already far too many. We 
want consistency across all modes.


> When I scale a rectangular opaque image I expect rectangular opaque 
> results. The Firefox implementation does not do this.

Let them know. This seems like a quality of implementation issue. I don't 
expect a 2x2 bitmap with four distinct colours to turn into the washes the 
other UAs do either.


> If I take a 1x1 pixel image and attempt to use it to cover up something 
> in another image by scaling it it will not cover up that other image.

So don't do that. Use fillRect().


On Fri, 10 Jul 2009, Gregg Tavares wrote:
> 
> I guess I don't understand. I'm new to the list so forgive me but I 
> thought HTML5 was still a working draft and that the canvas tag was part 
> of that draft. How is a draft immutable?

Once something gets implemented, it quickly becomes immutable, because 
sites start relying on it.

-- 
Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'



More information about the whatwg mailing list