使用PHP将SVG图像转换为PNG


111

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

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

理想情况下,我只想使用GD2库执行此操作,但也可以使用ImageMagick。我完全不知道如何执行此操作。

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


是否有旨在将SVG移植到VML的类?这样,您仍然可以拥有“ HTML5”类型的解决方案
Patrick

看我的答案。正是您所需要的

Answers:


142

您问这个很有趣,我最近是在我的工作网站上这样做的,我当时想我应该写一个教程...这是如何使用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) . '"  />';?>

(在使用clear / destroy之前),但是PNG作为base64存在问题,因此您可能必须将base64输出为jpeg

您可以在此处看到我为前雇主的销售区域图所做的示例:

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

完: 在此处输入图片说明

编辑

自编写以上内容以来,我提出了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或object标签嵌入svg时,您无法访问svg路径,因此,您必须将svg xml直接包含在网页html中,例如:

<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>

1
感谢您提供有关如何执行此操作的非常准确且实用的教程。我当然会使用您的解决方案作为备份,但渴望尝试并获得所有主要浏览器的svg兼容性。
Michael Berkompas 2011年

1
在IE8或更低版本中,不要求用户安装svg查看器插件,不支持SVG-从SVG维基百科页面:“所有主要的现代Web浏览器都直接支持和呈现SVG标记,但Microsoft Internet Explorer(IE)却是非常明显的例外[ 3] Internet Explorer 9 Beta支持基本的SVG功能集。[4]目前,对在Android下运行的浏览器的支持也受到限制。”
WebChemist 2011年

1
是的,但是svgweb似乎通过使用少量js和flash消除了所有不兼容性。这就是我的解决方案。
Michael Berkompas 2011年

2
我喜欢您干净快速的解决方案。就个人而言,与xml文件进行交互时,我更喜欢使用dom解析器来感觉比使用正则表达式更安全。像这样:$dom = new DOMDocument(); $dom->loadXML( $svg ); $dom->getElementsByTagName('image')->item(0)->setAttribute('id', $state); $svg = $dom->saveXML();
Tapper 2012年

一个xml解析器将是一个更安全的解决方案,尽管速度稍慢,但可以解决任何其他svg的问题……在这种情况下,正则表达式是安全的,因为我确保每个州的属性的格式均与(id =“ XX” style =“ fill:# XXXXXX”)。
WebChemist 2012年

11

您提到这样做是因为IE不支持SVG。

好消息是IE 确实支持矢量图形。好的,它采用的是一种称为VML的语言,只有IE才支持,而不是SVG,但它在那里,您可以使用它。

Google Maps等将检测浏览器功能,以确定是否提供SVG或VML。

然后是Raphael库,这是一个基于Java浏览器的图形库,它再次支持SVG或VML,具体取决于浏览器。

另一个可能有用的方法SVGWeb

所有这些都意味着您可以支持IE用户,而不必诉诸位图图形。

另请参见此问题的最佳答案,例如:XSL将SVG转换为VML


+1代表raphael,这绝对是一个不错的解决方案,值得一提,因为它出色地实现了跨浏览器矢量图形。
dmp

10

将SVG转换为透明PNG时,请不要忘记将其放在以下位置$imagick->readImageBlob()

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

在读取图像之前如何调用该方法,我收到一个错误“无法处理空的Imagick对象”。是的,我的imagick扩展程序已安装,因为它正在工作并转换图像。
Denis2310

6

这很简单,过去几周一直在为此工作。

您需要蜡染SVG工具包。下载文件并将其与要转换为JPEG的SVG放在同一目录中,还请确保先解压缩。

打开终端,然后运行以下命令:

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')

这很棒。谢谢你的提示。我将与perl结合使用它来批量处理从模板创建的SVG文件的负载。
simbabque 2012年

2

我不知道独立的PHP / Apache解决方案,因为这将需要一个可以读取和呈现SVG图像的PHP库。我不确定是否存在这样的库-我什么都不知道。

ImageMagick能够通过命令行或PHP绑定IMagick光栅化SVG文件,但似乎有许多怪癖和外部依赖项,例如此论坛线程中所示。我认为这仍然是最有前途的方法,如果我是你,这是我要研究的第一件事。


2

这是一种使用标准php GD工具将svg图片转换为gif的方法

1)您将图像放入浏览器的canvas元素中:

<canvas id=myCanvas></canvas>

<script>
var Key='picturename'
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
base_image = new Image();
base_image.src = myimage.svg;
base_image.onload = function(){

    //get the image info as base64 text string

    var dataURL = canvas.toDataURL();
    //Post the image (dataURL) to the server using jQuery post method
    $.post('ProcessPicture.php',{'TheKey':Key,'image': dataURL ,'h': canvas.height,'w':canvas.width,"stemme":stemme } ,function(data,status){ alert(data+' '+status) });
}
</script>    

然后在服务器(ProcessPicture.php)上将其从(默认)png转换为gif并保存。(您也可以另存为png,然后使用imagepng代替image gif):

//receive the posted data in php
$pic=$_POST['image'];
$Key=$_POST['TheKey'];
$height=$_POST['h'];
$width=$_POST['w'];
$dir='../gif/'
$gifName=$dir.$Key.'.gif';
 $pngName=$dir.$Key.'.png';

//split the generated base64 string before the comma. to remove the 'data:image/png;base64, header  created by and get the image data
$data = explode(',', $pic);
$base64img = base64_decode($data[1]);
$dimg=imagecreatefromstring($base64img); 

//in order to avoid copying a black figure into a (default) black background you must create a white background

$im_out = ImageCreateTrueColor($width,$height);
$bgfill = imagecolorallocate( $im_out, 255, 255, 255 );
imagefill( $im_out, 0,0, $bgfill );

//Copy the uploaded picture in on the white background
ImageCopyResampled($im_out, $dimg ,0, 0, 0, 0, $width, $height,$width, $height);

//Make the gif and png file 
imagegif($im_out, $gifName);
imagepng($im_out, $pngName);


-1
$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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.