用PHP将SVG图像转换为PNG
我正在开发一个Web项目,其中包含一个dynamic生成的美国地图,它根据一组数据着色不同的状态。
这个SVG文件给了我一个美国的空白地图,很容易改变每个国家的颜色。 难度在于IE浏览器不支持SVG,所以为了让我使用svg提供的方便的语法,我需要把它转换成JPG格式。
理想情况下,我只想用GD2库来做到这一点,但也可以使用ImageMagick。 我完全不知道如何做到这一点。
我们将考虑任何能够dynamic改变美国地图上的州的颜色的解决scheme。 关键是可以很容易地改变飞行中的颜色,并且它是跨浏览器的。 请仅使用PHP / Apache解决scheme。
这很有趣,你问了这个问题,最近我刚刚为我的工作网站做了这个,我想我应该写一个教程…以下是如何使用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();
正则expression式颜色replace的步骤可能会有所不同,具体取决于svgpathxml以及如何存储id和颜色值。 如果你不想在服务器上存储一个文件,你可以输出图像作为基础64像
<?php echo '<img src="data:image/jpg;base64,' . base64_encode($im) . '" />';?>
(之前你使用清除/销毁),但即与PNG问题为base64,所以你可能不得不输出base64为JPEG
你可以在这里看到我为前雇主的销售领域地图做的一个例子:
开始: https : //upload.wikimedia.org/wikipedia/commons/1/1a/Blank_US_Map_(states_only ).svg
完:
编辑
由于写了上述,我已经提出了2个改进的技术:
1)而不是正则expression式循环来改变填充状态,使用CSS来制作样式规则
<style type="text/css"> #CA,#FL,HI{ fill:blue; } #Al, #NY, #NM{ fill:#cc6699; } /*etc..*/ </style>
然后你可以做一个单一的文本replace注入你的css规则到svg中,然后再进行imagick jpeg / png创build。 如果颜色不改变,请检查以确保您的path标记中没有任何内联填充样式覆盖css。
2)如果你不需要实际创build一个jpeg / png图像文件(不需要支持过时的浏览器),你可以直接用jQuery来操纵svg。 当使用img或object标签embeddedsvg时,您不能访问svgpath,所以您必须直接在您的网页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>
另一个非常快速和准确的选项是无头浏览器PhantomJS(webkit)
你提到你这样做是因为IE不支持SVG。
好消息是IE 确实支持vectorgraphics。 好的,所以它的forms是一种叫做VML的语言,只有IE支持,而不是SVG,但它在那里,你可以使用它。
谷歌地图等,将检测浏览器的function,以确定是否服务于SVG或VML。
然后是Raphael库 ,这是一个基于Javascript的browswergraphics库,它支持SVG或VML,这取决于浏览器。
另一个可能有助于: SVGWeb 。
所有这一切意味着您可以支持您的IE用户,而无需诉诸位图graphics。
另请参阅此问题的最佳答案,例如: XSL将SVG转换为VML
将SVG转换为透明PNG时,不要忘记把这个BEFORE $ imagick-> readImageBlob():
$imagick->setBackgroundColor(new ImagickPixel('transparent'));
这很简单,在过去几周里一直在做这个工作。
你需要Batik SVG Toolkit 。 下载并将文件放在与要转换为JPEG的SVG相同的目录下 ,也请确保先解压缩。
打开terminal,运行这个命令:
java -jar batik-rasterizer.jar -m image/jpeg -q 0.8 NAME_OF_SVG_FILE.svg
这应该输出一个SVG文件的JPEG。 真的很容易。 你甚至可以把它放在一个循环中,并转换大量的SVG,
import os svgs = ('test1.svg', 'test2.svg', 'etc.svg') for svg in svgs: os.system('java -jar batik-rasterizer.jar -m image/jpeg -q 0.8 '+str(svg)+'.svg')
您可以使用canvg js库将SVG转换为PNG,更多信息请访问http://paksula.users.cs.helsinki.fi/svg_open_2010/demo.xhtml与所有主stream浏览器兼容!;
我在我的项目中使用它,实际上将SVG转换成PNG(在PHP的帮助下保存文件当然)
我不知道独立的PHP / Apache解决scheme,因为这需要一个可以读取和呈现SVG图像的PHP库。 我不确定这样的图书馆是否存在 – 我不知道。
ImageMagick能够通过命令行或PHP绑定IMagick来栅格化SVG文件,但似乎有一些怪癖和外部依赖关系,如本论坛主题中所示 。 我认为这仍然是最有希望的方式,如果我是你,我会首先考虑的。
$command = 'convert -density 300 '; if(Input::Post('height')!='' && Input::Post('width')!=''){ $command.='-resize '.Input::Post('width').'x'.Input::Post('height').' '; } $command.=$svg.' '.$source; exec($command); @unlink($svg);
或使用:potrace演示: Tool4dev.com
您可以使用Raphaël-JavaScript库并轻松实现。 它也将在IE中工作。