Convert Svg to Image (Jpeg, Png, etc.) in the Browser

Convert SVG to image (JPEG, PNG, etc.) in the browser

Here is how you can do it through JavaScript:

  1. Use the canvg JavaScript library to render the SVG image using Canvas: https://github.com/gabelerner/canvg
  2. Capture a data URI encoded as a JPG (or PNG) from the Canvas, according to these instructions: Capture HTML Canvas as gif/jpg/png/pdf?

When converting an svg to png in the browser using canvas api, embedded image in svg is randomly blank in Safari

This is a known and old bug.

For a workaround, it seems that a simple setTimeout(draw, 100) is enough, though that seems quite fragile to be honest (for instance 0 was working with my image but not with the font example in the bug report).

const ctx = document.querySelector("canvas").getContext("2d");
(async () => {
const png_blob = await fetch("https://upload.wikimedia.org/wikipedia/commons/4/47/PNG_transparency_demonstration_1.png").then(r=>r.ok&&r.blob());
const png_dataURL = await readAsDataURL(png_blob);
const anti_cache = "#" + Math.random();
const svg_markup = `<svg xmlns="http://www.w3.org/2000/svg" width="300" height="150" viewBox="0 0 100 100">
<rect width="10" height="10" fill="purple"/>
<image href="${ png_dataURL + anti_cache }" width="100" height="100"/>
</svg>`;
const svg_blob = new Blob([svg_markup], { type: "image/svg+xml" });
const img = new Image();
img.src = URL.createObjectURL(svg_blob);
img.onload = (evt) => {
setTimeout(
() => ctx.drawImage(img, 0, 0),
100
);
};
})().catch(console.error);

function readAsDataURL(blob) {
const reader = new FileReader();
return new Promise((res, rej) => {
reader.onload = () => res(reader.result);
reader.onerror = rej;
try {
reader.readAsDataURL(blob);
}
catch(err) {
rej(err);
}
});
}
<canvas></canvas>

Convert a SVG to a PNG/JPEG without using canvas in a serverless function

The best way to deal with this that I have found so far is by using a headless chrome and getting a screenshot. As an example by using puppeteer I could get a screenshot of the viewport like follows,

const browser = await puppeteer.launch();
const page = await browser.newPage();

let yourName = 'world'

const svg = `
<svg fill="none" viewBox="0 0 600 400" width="600" height="400" xmlns="http://www.w3.org/2000/svg">
<foreignObject width="100%" height="100%">
<div xmlns="http://www.w3.org/1999/xhtml">
<style>
.title {
font-size: 10vh;
font-weight: regular;
background-color: #ffddff;
}
</style>

<p class="title">Hello ${yourName}</p>

</div>
</foreignObject>
</svg>
`;

await page.setViewport({ width: 2048, height: 1170 });
await page.setContent(svg);

console.log(await page.content());
await page.screenshot({path: 'screenshot.png'});
await browser.close();

Then it will be easy to send the png as the response.

In browser conversion of svg to png image (cross browser including IE)

IE9 seem to indeed support the canvas element as per https://msdn.microsoft.com/fr-fr/library/ff975241(v=vs.85).aspx

The following sample/test code for toDataURL works for me in IE11 : http://samples.msdn.microsoft.com/Workshop/samples/canvas/todataurl.html

The fiddle you gave does not work in IE11 ; looking at the console errors, it leads to the fact that you cannot call drawImage before the image has finished its rendering. IE Throws a

call to unsupported method or attributes of a method

Adding a setTimeout allow IE to render the dynamic image and bypass this error.

But it then leads to a

Security Error

because it seems that IE has tainted the canvas because of some "cross origin" issue

SecurityError
The img or video element is not of the same origin or domain
as the document that owns the canvas element. Versions earlier
than Internet Explorer 10 use SECURITY_ERR.

IE seems to be tainting all images filled with SVG for security reasons - SVG tained canvas IE security error toDataURL

I managed to have a working version using canvg, which transforms an SVG file into canvas instructions - https://github.com/gabelerner/canvg

the solution boils down to

var svg = Highcharts.getSVG(charts);
var mycanvas = document.createElement('canvas');
canvg(mycanvas, svg)
console.log(mycanvas.toDataURL("image/png"))

check this fiddle http://jsfiddle.net/6bxqbaeb/1/ which works in IE11



Related Topics



Leave a reply



Submit