0

I am working on a PHP script in which I will need to convert SVG to png and to save CPU usage and server load it's better to do the conversion in the client site(Browser) and this is possible with only Javascript. Html code :

    <div>
 <svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="800" height="420" id="svg"><image height="420" width="800" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://upload.wikimedia.org/wikipedia/commons/7/76/Tabby_cat-hello.jpg" transform="matrix(1 0 0 1 0 0)" class="draggable" type="staticimg" id="1465449556528" ></image> </svg>
    <a id='imgId'>Save</a>
</div>
<canvas></canvas>

Javascript code:

    var svg = document.getElementsByTagName('svg')[0];
var svg_xml = (new XMLSerializer()).serializeToString(svg),
    blob = new Blob([svg_xml], {type:'image/svg+xml;charset=utf-8'}),
    url = window.URL.createObjectURL(blob);

var img = new Image();
img.width = 730;
img.height = 300;
img.onload = function(){
    var canvas = document.createElement('canvas');
    canvas.width = 730;
    canvas.height = 300;

    var ctx = canvas.getContext('2d');
    ctx.drawImage(img, 0, 0, 730, 300);

    window.URL.revokeObjectURL(url);
    var canvasdata = canvas.toDataURL('image/png');
    var a = document.getElementById('imgId');
    a.download = "export_" + Date.now() + ".png";
    a.href=canvasdata;   
}
img.src = url   

the svg works just find but i cant convert to png. JSFIDDLE : http://jsfiddle.net/vyLtxgh4/6/

Belatar Yassine
  • 153
  • 2
  • 10
  • What I understand from your code sample is that you're trying to convert png to png? – Igwe Kalu Jun 17 '16 at 20:19
  • @IgweKalu Im trying to convert the svg to png – Belatar Yassine Jun 17 '16 at 20:21
  • I am not sure what you mean, but the upper html code snippet does not convert SVG to PNG. It just embeds a PNG image into an SVG image. See: https://developer.mozilla.org/en-US/docs/Web/SVG/Tutorial/SVG_Image_Tag I don't see where in the lower code snippet you try to do the conversion. What you need to do abstractly is rasterizing a rendered SVG. See this question for example: http://stackoverflow.com/questions/3975499/convert-svg-to-image-jpeg-png-etc-in-the-browser – Thomas Jun 17 '16 at 20:24
  • @Thomas When trying to convert svg to canvas it works perfect but the problem is when i try to convert canvas to png because the svg has external images (Using the method included in the question) – Belatar Yassine Jun 17 '16 at 20:28
  • @thomas please check this : http://jsfiddle.net/vyLtxgh4/6/ – Belatar Yassine Jun 17 '16 at 20:39
  • @IgweKalu Please check the update! – Belatar Yassine Jun 17 '16 at 20:43
  • @BelatarYassine Yep, the second jsfiddle example works. In the first example though, I don't see where you try to actually do the conversion? – Thomas Jun 17 '16 at 20:43
  • @Thomas it was just an error the second jsfiddle doesn't convert SVG to png I only see a blank image when downloading. It is because I use external images in the main SVG . What should I do to solve this issue ? – Belatar Yassine Jun 17 '16 at 20:46
  • `img` element can't load external resources, so you need to append a dataURI version of your external image insise the markup. There is duplicate question I already answered somewhere (can't find it rn) and I wrote [this script](https://github.com/Kaiido/SVG2Bitmap) (still in alpha release) which does handle this case if the external images are served with correct cross-origin headers. Also note that some UAs has trouble with xlink in blobs, better hse a plain dataUri version. – Kaiido Jun 18 '16 at 00:50
  • @Kaiido I included you script but don't know how to use it . SVG2Bitmap(sourceElement, [receiver] [, {optionalParameters}]); please can you explain more ? – Belatar Yassine Jun 18 '16 at 02:18
  • SourceElement is either an svg element, either an object element or an iframe pointing to an svg file. Receiver is either null, in this case the source element is replaced with the canvas one, an img element where the dataUrl of the canvas willl be passed, or a callback function with the resulting canvas passed as first parameter. – Kaiido Jun 18 '16 at 04:25

1 Answers1

1

Building on top of your code, I came up with the following snippets.

The solution is not perfect, but I think it can serve as starting point for you to continue development.


HTML

First, I am using an additional javascript library that needs to be loaded. It can be found here: Javascript SVG parser and renderer on Canvas

<script type="text/javascript" src="http://gabelerner.github.io/canvg/canvg.js"></script>

Then your original code follows with some reformatting and an additional canvas element.

<div>
    <svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="800" height="420" id="svg">
        <image height="420" width="800" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://upload.wikimedia.org/wikipedia/commons/7/76/Tabby_cat-hello.jpg" transform="matrix(1 0 0 1 0 0)" class="draggable" type="staticimg" id="1465449556528" ></image> 
    </svg>
    <a id="imgId" download="Canvas.png" href="#">Save</a>
</div>
<canvas id="canvas" width="730px" height="300px"></canvas> 

JavaScript

Second, in the JavaScript part I use the loaded canvg.js library to write the serialized svg code to the canvas. The function downloadCanvas() is then attached as a click event listener on the imgId hyperlink element. So, the potentially expensive conversion to a data url string is only done on demand (=click).

var svg = document.getElementsByTagName('svg')[0];
var svg_xml = (new XMLSerializer()).serializeToString(svg);
svg.remove();

// write serialized svg to canvas
canvg('canvas', svg_xml, {useCORS: true});

// create canvas data on demand
function downloadCanvas() {
    this.href = canvas.toDataURL('image/png');
};
document.getElementById('imgId').addEventListener('click', downloadCanvas, false);

Stackoverflow Snippet

var svg = document.getElementsByTagName('svg')[0];
var svg_xml = (new XMLSerializer()).serializeToString(svg);
svg.remove();

canvg('canvas', svg_xml, {
  useCORS: true
});

function downloadCanvas() {
  this.href = canvas.toDataURL('image/png');
};
document.getElementById('imgId').addEventListener('click', downloadCanvas, false);
<script src="http://gabelerner.github.io/canvg/canvg.js"></script>
<div>
  <svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" version="1.1" width="800" height="420" id="svg">
    <image height="420" width="800" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://upload.wikimedia.org/wikipedia/commons/7/76/Tabby_cat-hello.jpg" transform="matrix(1 0 0 1 0 0)" class="draggable" type="staticimg" id="1465449556528"></image>
  </svg>
  <a id="imgId" download="Canvas.png" href="#">Save</a>
</div>
<canvas id="canvas" width="730px" height="300px"></canvas>
Thomas
  • 2,155
  • 16
  • 22