Render SVG to PNG, JPG or WebP at a chosen size, with the size worked out from the file by the rules that define it and checked against the browser's own rendering.
Initializing in your browser…
Convert between the formats a browser can really write, then open the output and name the format its first bytes say it is. AVIF, BMP and GIF are disabled because a canvas returns a PNG for all three.
Trace a PNG or JPG into real SVG paths, with holes that stay holes and transparency that is not read as black. The page counts the pixels its own vector differs from the picture, and at the exact setting that count is zero.
Resize with the filter named (Lanczos, Mitchell, Catmull-Rom, bilinear, box or nearest) and the option to average LIGHT rather than stored bytes, which is worth 1.24 stops on a detailed picture.
A print graphic whose root element says width="10cm" height="5cm".
In the file
<svg viewBox="0 0 100 50" width="10cm" height="5cm">
What the page shows
The size this file asks for: 377.95 by 188.98 the browser draws it at 378 by 189, which agrees width 10cm is 377.95 CSS pixels at the 96 pixels an inch CSS Values 4 section 6.2 fixes
The previous version used parseFloat, which reads "10cm" as 10, and produced a 10 by 5 PIXEL image: 37.8 times too small in each direction, from a graphic meant for print. The unit is converted by the rule that defines it, and the browser is asked the same question so the two answers sit side by side.
Render an SVG to PNG, JPG or WebP at a chosen size, with the size worked out from the file rather than guessed. Centimetres, percentages and a viewBox with no width are all handled by the rules that define them, and the browser is asked the same question so the two answers can be compared on screen.
"What size is this SVG" has a definite answer, and the tool used to guess at it. The size comes from the width, height and viewBox attributes fed into the CSS default sizing algorithm (CSS Images 3 section 5.3), and the browser implements that algorithm, so loading the same file into an image element and reading naturalWidth gives a second answer that can be compared. Measured on 2026-09-05 at 1x, the previous version disagreed with the browser on four of seven test files, and the PNG it produced was its own wrong answer every time.
Four separate causes, each one line. The viewBox was split on whitespace, and SVG 1.1 section 7.7 allows comma-wsp, so viewBox="0,0,160,80" produced NaN. The width and height attributes each overrode the viewBox independently, so a file with a width and no height took its height from the viewBox and came out the wrong shape: a 1:1 drawing declared width="200" rasterised to 200 by 100. parseFloat("10cm") is 10, so every CSS absolute unit was read as pixels and a 10 by 5 centimetre graphic became a 10 by 5 PIXEL image, 37.8 times too small in each direction. And parseFloat("100%") is 100, so a percentage was read as a pixel count although a percentage is not an intrinsic size at all. All seven files now agree with the browser and with the specification, and the page prints the reasoning: which attribute gave what, the conversion factor for a physical unit, and the intrinsic ratio the viewBox implies.
preserveAspectRatio was ignored entirely, and that matters as soon as you type a size. Asking for a 400 by 200 box from a square drawing has three possible answers and SVG 1.1 section 7.8 says which: keep the shape and letterbox, or stretch. There is a control for it now, the page reports the bars on each side and what share of the output they take, and the rendering honours the choice. That last part is not free: drawImage with a destination rectangle STRETCHES the picture into it, because preserveAspectRatio maps a viewBox into the SVG's own viewport and has no say over how a canvas scales the result. Keeping the shape therefore means computing the letterboxed rectangle and drawing there, and the measurement shows the difference: the same file in the same box has 24,334 painted pixels one way and 48,492 the other.
After the render, the file is read back rather than assumed. The format is sniffed off the produced bytes and printed with its first bytes beside the verdict, because a canvas returns a PNG for a type it cannot encode and says nothing; the three formats are probed on a one-pixel canvas at load and any this browser cannot write is disabled with the reason. The extension comes from what the file IS rather than from what was asked for. Transparency in the result is counted, and asking for JPEG with a transparent background warns before the fact that JPEG has no alpha channel and the encoder composites against black. Finally, an SVG loaded into an image element runs no scripts and fetches nothing from outside itself, so a file referencing an external font or image fails to draw at all; the page says that rather than reporting a generic failure.
The browser rasterises the vector geometry at the output resolution, so 2x or 4x gives genuinely crisp pixels rather than an enlargement of a small bitmap.
377.95 pixels at 1x. CSS Values 4 section 6.2 fixes an inch at 96 reference pixels and every other absolute unit as a fraction of it, so a centimetre is 96 divided by 2.54. The previous version read the number and dropped the unit, producing a 10 pixel image.
Because it has a viewBox and no width or height. A viewBox gives a shape but not a size, so the CSS default sizing algorithm uses the 300 by 150 default object size constrained to that shape. Type a width if you want a different one.
Because the drawing is a different shape and you asked to keep it. SVG 1.1 section 7.8 decides that from preserveAspectRatio, and the page tells you how wide the bars are before you render. Switch to filling the box exactly to stretch instead.
Only fonts the browser already has. An SVG loaded into an image element fetches nothing from outside itself, so a webfont referenced by URL will not load. Convert text to paths in the source if the typeface matters.
Images are decoded, edited, and exported entirely inside this browser tab. No originals, exports, or metadata are uploaded.