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

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

I want to convert SVG into bitmap images (like JPEG, PNG, etc.) through JavaScript.


Solution 1:

Here is how you can do it through JavaScript:

  1. Use the canvg JavaScript library to render the SVG image using Canvas:
  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?

Solution 2:

jbeard4 solution worked beautifully.

I’m using Raphael SketchPad to create an SVG. Link to the files in step 1.

For a Save button (id of svg is “editor”, id of canvas is “canvas”):

$("#editor_save").click(function() {

// the canvg call that takes the svg xml and converts it to a canvas
canvg('canvas', $("#editor").html());

// the canvas calls to output a png
var canvas = document.getElementById("canvas");
var img = canvas.toDataURL("image/png");
// do what you want with the base64, write to screen, post to server, etc...

Solution 3:

This seems to work in most browsers:

function copyStylesInline(destinationNode, sourceNode) {
   var containerElements = ["svg","g"];
   for (var cd = 0; cd < destinationNode.childNodes.length; cd++) {
       var child = destinationNode.childNodes[cd];
       if (containerElements.indexOf(child.tagName) != -1) {
            copyStylesInline(child, sourceNode.childNodes[cd]);
       var style = sourceNode.childNodes[cd].currentStyle || window.getComputedStyle(sourceNode.childNodes[cd]);
       if (style == "undefined" || style == null) continue;
       for (var st = 0; st < style.length; st++){
  [st], style.getPropertyValue(style[st]));

function triggerDownload (imgURI, fileName) {
  var evt = new MouseEvent("click", {
    view: window,
    bubbles: false,
    cancelable: true
  var a = document.createElement("a");
  a.setAttribute("download", fileName);
  a.setAttribute("href", imgURI);
  a.setAttribute("target", '_blank');

function downloadSvg(svg, fileName) {
  var copy = svg.cloneNode(true);
  copyStylesInline(copy, svg);
  var canvas = document.createElement("canvas");
  var bbox = svg.getBBox();
  canvas.width = bbox.width;
  canvas.height = bbox.height;
  var ctx = canvas.getContext("2d");
  ctx.clearRect(0, 0, bbox.width, bbox.height);
  var data = (new XMLSerializer()).serializeToString(copy);
  var DOMURL = window.URL || window.webkitURL || window;
  var img = new Image();
  var svgBlob = new Blob([data], {type: "image/svg+xml;charset=utf-8"});
  var url = DOMURL.createObjectURL(svgBlob);
  img.onload = function () {
    ctx.drawImage(img, 0, 0);
    if (typeof navigator !== "undefined" && navigator.msSaveOrOpenBlob)
        var blob = canvas.msToBlob();         
        navigator.msSaveOrOpenBlob(blob, fileName);
    else {
        var imgURI = canvas
            .replace("image/png", "image/octet-stream");
        triggerDownload(imgURI, fileName);
  img.src = url;

Solution 4:

Here’s a server side solution based on PhantomJS. You can use JSONP to make a cross domain call to the image service:

For example:


Then you can display image with img tag:

<img src="data:image/png;base64, [base64 data]"/>

It works across browser.

Solution 5:

change svg to match your element

function svg2img(){
    var svg = document.querySelector('svg');
    var xml = new XMLSerializer().serializeToString(svg);
    var svg64 = btoa(xml); //for utf8: btoa(unescape(encodeURIComponent(xml)))
    var b64start = 'data:image/svg+xml;base64,';
    var image64 = b64start + svg64;
    return image64;

Solution 6:

I recently discovered a couple of image tracing libraries for JavaScript that indeed are able to build an acceptable approximation to the bitmap, both size and quality. I’m developing this JavaScript library and CLI :

Which provides unified API for all of them, supporting browser and node, non depending on DOM, and a Command line tool.

For converting logos/cartoon/like images it does excellent job. For photos / realism some tweaking is needed since the output size can grow a lot.

It has a playground although right now I’m working on a better one, easier to use, since more features has been added: