Open Bug 1547776 Opened 5 years ago Updated 8 months ago

Canvas drawImage does not correctly scale images using an SVG source

Categories

(Core :: Graphics: Canvas2D, defect, P3)

66 Branch
defect

Tracking

()

UNCONFIRMED

People

(Reporter: simon.sarris, Unassigned)

References

(Regression)

Details

(Keywords: parity-chrome, parity-edge, regression, Whiteboard: [gfx-noted])

Attachments

(6 files)

Attached file reproducible example

User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36

Steps to reproduce:

Simple repro: https://codepen.io/simonsarris/pen/mOJdQe

This correctly works in other major browsers.

Code also here and attached, with example of FF vs Chrome vs IE Edge.

<body>

<canvas id="canvas" style="border: solid 3px red; width:400px; height:400px"></canvas>
<p>The above should look "squished", as it is 391x391 drawn into the area 100x391. For reference the original SVG:</p>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/1/1a/SVG_example_markup_grid.svg">
</img></p>

</body>
<script>
var can = document.getElementById('canvas');
can.width = 400;
can.height = 400;
var ctx = can.getContext('2d');

var img = new Image();

// like its 1999:
img.onload = function() {
// The SVG's real dimensions are 391x391, we are going to draw it at
// 100x391, this will produce a squished image (this is good)
// If it produces a scaled image (100x100), this is bad
ctx.drawImage(img, 0, 0, 100, 391);
}

img.src = "https://upload.wikimedia.org/wikipedia/commons/1/1a/SVG_example_markup_grid.svg";

</script>

Actual results:

The SVG image is scaled down uniformly, instead of scaled differently on X (should be scaled) and Y (should not be scaled)

Expected results:

A destination width and height of 100x391 should draw a source

Attached image examples.png
Component: General → Canvas: 2D

Regression Window: https://hg.mozilla.org/integration/mozilla-inbound/pushloghtml?fromchange=3488976ecf0f&tochange=3d51132a0099

Regressed by: 3d51132a0099aed9bd4dfc16584eff231253a35e Seth Fowler — Bug 1043560 - Refactor the imgIContainer::Draw API. r=tn,dholbert,jwatt,mwu,mattwoodrow,roc sr=jrmuizel

Status: UNCONFIRMED → NEW
Has Regression Range: --- → yes
Has STR: --- → yes
Ever confirmed: true
Keywords: regression
Regressed by: 1043560

If you don't want to preserve the aspect ratio then indicate you don't want to:

img.src = "https://upload.wikimedia.org/wikipedia/commons/1/1a/SVG_example_markup_grid.svg#svgView(preserveAspectRatio(none))";

Or alternatively edit the SVG_example_markup_grid.svg so that it has preserveAspectRatio="none" on its root element if you control that file.

Is ignoring the preserveAspectRatio value actually useful behaviour by Chrome/Edge? What if you do want to preserve the aspect ratio?

But this isn't a matter of SVG rendering, it is one of Canvas context rendering. As soon as something is to be painted on the HTML Canvas context, shouldn't it follow the context's rules for drawing?

It is a feature of the Canvas Context that calls to context.drawImage(img, x, y, width, height, [ignoring src args]) will scale (axis independent) any image input according to the provided width and height. Preserving the aspect ratio may be a feature of how SVG draws itself, but when taking an SVG source and drawing it to a Canvas context with drawImage, I think the expectation that other browsers are following is to use the canvas context's rules for how to draw.

The priority flag is not set for this bug.
:lsalzman, could you have a look please?

For more information, please visit auto_nag documentation.

Flags: needinfo?(lsalzman)
Flags: needinfo?(lsalzman)
Priority: -- → P3
Whiteboard: [gfx-noted]

I spent a while googling while trying to figure out what was going on here. I was about to write a ticket very similar to this one.

As far as I can tell, this ticket is the only/most-accessible place on the internet that describes the step of modifying preserveAspectRatio being necessary to allow CanvasRenderingContext2D#drawImage with 9 arguments to work for svgs.

The 9 argument variant of drawImage is designed to allow the programmer to map one rectangle in the source image to another inside the canvas. I can understand the thinking behind preserving aspect ratio, but if the expected behavior of the 9 argument variant is going to be violated it would be nice to have documentation showing working code.

If this behavior is going to stay the way it is, I think it would be helpful to future devs to have working examples for these cases (if not more):

  • svg downloaded by setting image.src
  • svg as base64 dataUrl

this issue, combined with #700533, makes using drawImage with svgs very tricky on Firefox.

It should be noted that the 3 and 5 argument variants also violate expectations when preserveAspectRatio has not been changed.

Setting status back to UNCONFIRMED since w3c at the moment seem to be suggesting that Firefox has the intended rendering.

Status: NEW → UNCONFIRMED
Ever confirmed: false
Severity: normal → S3

I've identified this ticket as it's affecting me in doing an off-screen rendering to perform some calculations on a user-provided image.

preserveAspectRadio(none) provided an explicit workaround for me, and like the earlier poster I only found it from this ticket.

But my intuition is this is not correct to require this because as a JavaScript author I would expect the default rendering of equivalent SVG and PNG images to be equivalent. The PNG does not preserve its aspect ratio on any browser when provided drawImage(), and therefore I would not expect the SVG to do this.

Attached file test-image.html
Attached image ellipse.svg
Attached image ellipse.png

We have found that the use of preserveAspectRadio(none) has a negative side-effects on Safari browsers (tested version 16.1 here), giving a different bounding box. Therefore it can't be applied unconditionally, and something like the following is necessary:

if (firefox)
    img.src = `${url}#svgView(preserveAspectRatio(none))`;
else
    img.src = url;
Duplicate of this bug: 1842572
See Also: → 700533
See Also: → 1846565
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: