Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert embedded SVG to PNG in-place

Tags:

html

svg

I'm generating HTML from a Docbook source while using SVG for images (converted from MathML). This works fine for some browsers that can interpret SVG, but fails for others.

What I would really like is to add a post-processing step that will convert SVG to PNG "in-place" (within the HTML).

So something like this:

<body>     <svg xmlns="http://www.w3.org/2000/svg" version="1.1">         <circle cx="50" cy="50" r="30" />     </svg> </body> 

Would get seamlessly converted to this:

<body>     <img src="img0001.png" /> </body> 

And I would get a converted PNG alongside.

Is there something that will do this?

like image 839
jjkparker Avatar asked Mar 25 '11 14:03

jjkparker


People also ask

How do I convert SVG to PNG locally?

Navigate to an . svg file, right click on it and click on the context menu item 'Save SVG as PNG. Lets you click on the extension icon or right click on an . svg file and choose Save SVG as PNG.

How do I change SVG to PNG in HTML?

Create an img and set its src to your SVG. Create an HTML5 canvas and use drawImage() to draw that image to your canvas. Use toDataURL() on the canvas to get a base64 encoded PNG. Create an img and set it's src to that data URL.

Can you turn an SVG into a PNG?

Use Adobe Photoshop to convert SVG images to PNG images. Get lossless compression, preserve image resolution, and lower your file size by converting from SVG to PNG. Use Photoshop for a fast way to turn large file formats into smaller, easier-to-use graphic types. Open your SVG file in Photoshop.

How do I save an SVG as a picture?

You can use the Save As feature to save to the SVG format directly. Choose File > Save As from the Menu Bar. You can create a file and then choose File > Save As to save the file.

How do I convert a SVG image to a PNG image?

The idea is to create that object from the svg code, load it to an image element, then write that image to canvas. We can then use toDataURL() to make a base64 encoded PNG image and we’re done. First step is to create the url, but that will fail unless the svg code has its namespace defined, so we’ll poke the svg code

How do I open and edit an SVG file?

It is possible to use Adobe programs for opening and editing SVG files. Just be sure to install the SVG Kit for Adobe Creative Suite plug-in first. Converting SVG files is possible with the aid of a few online tools. For conversion to non-vector file types, try our SVG to GIF or SVG to PDF tools.

Why do PNG files look so bad compared to SVG files?

On Retina Displays, the PNG that you see previewed and ultimately saved looks terrible compared to the SVG, because it's generated at the given resolution. Retina displays then have to scale this up, usually by a factor of x2.

How to convert an SVG string to Base64 PNG using @Param?

* converts an svg string to base64 png using the domUrl * @param {string} svgText the svgtext * @param {number} [margin=0] the width of the border - the image size will be height+margin by width+margin


2 Answers

I ran into this problem over the past weekend, and ended up writing a simple library to do more or less what Phrogz describes. It also hard codes the target SVG's style in order to avoid rendering issues. Hopefully the next person looking for a way to do this can simply use my code and move on to the more interesting challenges!

P.S. I only tested this in Chrome.

// Takes an SVG element as target function svg_to_png_data(target) {   var ctx, mycanvas, svg_data, img, child;    // Flatten CSS styles into the SVG   for (i = 0; i < target.childNodes.length; i++) {     child = target.childNodes[i];     var cssStyle = window.getComputedStyle(child);     if(cssStyle){        child.style.cssText = cssStyle.cssText;     }   }    // Construct an SVG image   svg_data = '<svg xmlns="http://www.w3.org/2000/svg" width="' + target.offsetWidth +              '" height="' + target.offsetHeight + '">' + target.innerHTML + '</svg>';   img = new Image();   img.src = "data:image/svg+xml," + encodeURIComponent(svg_data);    // Draw the SVG image to a canvas   mycanvas = document.createElement('canvas');   mycanvas.width = target.offsetWidth;   mycanvas.height = target.offsetHeight;   ctx = mycanvas.getContext("2d");   ctx.drawImage(img, 0, 0);    // Return the canvas's data   return mycanvas.toDataURL("image/png"); }  // Takes an SVG element as target function svg_to_png_replace(target) {   var data, img;   data = svg_to_png_data(target);   img = new Image();   img.src = data;   target.parentNode.replaceChild(img, target); } 
like image 33
user3229542 Avatar answered Sep 24 '22 21:09

user3229542


Demo: http://phrogz.net/SVG/svg_to_png.xhtml

  1. Create an img and set its src to your SVG.
  2. Create an HTML5 canvas and use drawImage() to draw that image to your canvas.
  3. Use toDataURL() on the canvas to get a base64 encoded PNG.
  4. Create an img and set it's src to that data URL.
var mySVG    = document.querySelector('…'),      // Inline SVG element     tgtImage = document.querySelector('…'),      // Where to draw the result     can      = document.createElement('canvas'), // Not shown on page     ctx      = can.getContext('2d'),     loader   = new Image;                        // Not shown on page  loader.width  = can.width  = tgtImage.width; loader.height = can.height = tgtImage.height; loader.onload = function(){   ctx.drawImage( loader, 0, 0, loader.width, loader.height );   tgtImage.src = can.toDataURL(); }; var svgAsXML = (new XMLSerializer).serializeToString( mySVG ); loader.src = 'data:image/svg+xml,' + encodeURIComponent( svgAsXML ); 

However, this answer (and all client-side only solutions) require the browser to support SVG, which may make it useless for your specific needs.

Edit: This answer assumes that the SVG is available as a separate URL. Due to the problems described in this question I cannot get the above to work with an SVG document embedded in the same document performing the work.

Edit 2: The problems described in that other question have been overcome by improvements to Chrome and Firefox. There is still the limitation that the <svg> element must have width="…" height="…" attributes for Firefox to allow it to be drawn to a canvas. And Safari currently taints the entire canvas whenever you draw any SVG to it (regardless of source) but that should change soon.

like image 181
Phrogz Avatar answered Sep 24 '22 21:09

Phrogz