使用 PHP 将 SVG 图像转换为 PNG

2022-08-30 07:11:45

我正在开发一个Web项目,该项目涉及根据一组数据动态生成的美国地图,为不同州着色。

这个SVG文件为我提供了一个很好的美国空白地图,并且很容易更改每个州的颜色。困难在于IE浏览器不支持SVG,因此为了让我使用svg提供的便捷语法,我需要将其转换为JPG。

理想情况下,我只想用GD2库来做这件事,但也可以使用ImageMagick。我完全不知道如何做到这一点。

任何允许我动态更改美国地图上各州颜色的解决方案都将被考虑。关键是很容易动态更改颜色,并且是跨浏览器的。请仅提供 PHP/Apache 解决方案。


答案 1

你问这个很有趣,我最近刚刚为我的工作网站做了这个,我想我应该写一个教程......以下是如何使用PHP / Imagick做到这一点,它使用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();

正则表达式颜色替换的步骤可能会有所不同,具体取决于 svg 路径 xml 以及 id 和颜色值的存储方式。如果您不想在服务器上存储文件,则可以将图像输出为base 64,例如

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

(在使用清除/销毁之前),但IE存在PNG作为base64的问题,因此您可能必须将base64输出为jpeg

你可以在这里看到一个我为前雇主的销售区域地图所做的示例:

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

完成:enter image description here

编辑

自从写了上面的文章,我提出了2个改进的技术:

1)而不是正则表达式循环来改变填充状态,使用CSS来制作样式规则,例如

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

然后,您可以执行单个文本替换以将css规则注入svg,然后再继续进行imagick jpeg / png创建。如果颜色没有变化,请检查以确保路径标签中没有任何覆盖 css 的内联填充样式。

2)如果您不必实际创建jpeg / png图像文件(并且不需要支持过时的浏览器),则可以使用jQuery直接操作svg。使用 img 或对象标记嵌入 svg 时,您无法访问 svg 路径,因此您必须直接在网页 html 中包含 svg xml,如下所示:

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

然后更改颜色就像这样简单:

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

答案 2

将SVG转换为透明PNG时,不要忘记将其放在前面:$imagick->readImageBlob()

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

推荐