Convert SVG Image To PNG With PHP


Answer :

That's funny you asked this, I just did this recently for my work's site and I was thinking I should write a tutorial... Here is how to do it with PHP/Imagick, which uses ImageMagick:



$usmap = '/path/to/blank/us-map.svg';
$im = new Imagick();
$svg = file_get_contents($usmap);

/*loop to color each state as needed, something like*/
$idColorArray = array(
"AL" => "339966"
,"AK" => "0099FF"
...
,"WI" => "FF4B00"
,"WY" => "A3609B"
);

foreach($idColorArray as $state => $color){
//Where $color is a RRGGBB hex value
$svg = preg_replace(
'/id="'.$state.'" style="fill:#([0-9a-f]{6})/'
, 'id="'.$state.'" style="fill:#'.$color
, $svg
);
}

$im->readImageBlob($svg);

/*png settings*/
$im->setImageFormat("png24");
$im->resizeImage(720, 445, imagick::FILTER_LANCZOS, 1); /*Optional, if you need to resize*/

/*jpeg*/
$im->setImageFormat("jpeg");
$im->adaptiveResizeImage(720, 445); /*Optional, if you need to resize*/

$im->writeImage('/path/to/colored/us-map.png');/*(or .jpg)*/
$im->clear();
$im->destroy();


the steps regex color replacement may vary depending on the svg path xml and how you id & color values are stored. If you don't want to store a file on the server, you can output the image as base 64 like



<?php echo '<img src="data:image/jpg;base64,' . base64_encode($im) . '"  />';?>


(before you use clear/destroy) but ie has issues with PNG as base64 so you'd probably have to output base64 as jpeg



you can see an example here I did for a former employer's sales territory map:



Start: https://upload.wikimedia.org/wikipedia/commons/1/1a/Blank_US_Map_(states_only).svg





Finish: enter image description here



Edit



Since writing the above, I've come up with 2 improved techniques:



1) instead of a regex loop to change the fill on state , use CSS to make style rules like



<style type="text/css">
#CA,#FL,HI{
fill:blue;
}
#Al, #NY, #NM{
fill:#cc6699;
}
/*etc..*/
</style>


and then you can do a single text replace to inject your css rules into the svg before proceeding with the imagick jpeg/png creation. If the colors don't change, check to make sure you don't have any inline fill styles in your path tags overriding the css.



2) If you don't have to actually create a jpeg/png image file (and don't need to support outdated browsers), you can manipulate the svg directly with jQuery. You can't access the svg paths when embedding the svg using img or object tags, so you'll have to directly include the svg xml in your webpage html like:



<div>
<?php echo file_get_contents('/path/to/blank/us-map.svg');?>
</div>


then changing the colors is as easy as:



<script type="text/javascript" src="/path/to/jquery.js"></script>
<script type="text/javascript">
$('#CA').css('fill', 'blue');
$('#NY').css('fill', '#ff0000');
</script>


You mention that you are doing this because IE doesn't support SVG.



The good news is that IE does support vector graphics. Okay, so it's in the form of a language called VML which only IE supports, rather than SVG, but it is there, and you can use it.



Google Maps, among others, will detect the browser capabilities to determine whether to serve SVG or VML.



Then there's the Raphael library, which is a Javascript browswer-based graphics library, which supports either SVG or VML, again depending on the browser.



Another one which may help: SVGWeb.



All of which means that you can support your IE users without having to resort to bitmap graphics.



See also the top answer to this question, for example: XSL Transform SVG to VML



When converting SVG to transparent PNG, don't forget to put this BEFORE $imagick->readImageBlob():



$imagick->setBackgroundColor(new ImagickPixel('transparent'));


Comments

Popular posts from this blog

Converting A String To Int In Groovy

"Cannot Create Cache Directory /home//.composer/cache/repo/https---packagist.org/, Or Directory Is Not Writable. Proceeding Without Cache"

Android How Can I Convert A String To A Editable