使用PHP将SVG图像转换为PNG

Mic*_*pas 104 php svg jpeg imagemagick gd2

我正在开发一个Web项目,该项目涉及动态生成的美国地图,该地图基于一组数据着色不同的状态.

这个SVG文件给了我一张很好的美国空白地图,很容易改变每个州的颜色.困难在于IE浏览器不支持SVG,所以为了让我使用svg提供的方便语法,我需要将它转换为JPG.

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

将考虑允许我动态改变美国地图上的状态颜色的任何解决方案.关键是它可以很容易地改变颜色并且它是跨浏览器的.请给我PHP/Apache解决方案.

Web*_*ist 135

你问这个很有趣,我最近刚刚为我的工作网站做了这个,我想我应该写一个教程......以下是如何用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();
Run Code Online (Sandbox Code Playgroud)

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

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

(在你使用clear/destroy之前)但是因为PNG作为base64存在问题所以你可能不得不输出base64作为jpeg

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

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

完: 在此输入图像描述

编辑

自从编写上述内容后,我提出了两种改进的技术:

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

<style type="text/css">
#CA,#FL,HI{
    fill:blue;
}
#Al, #NY, #NM{
    fill:#cc6699;
}
/*etc..*/
</style>
Run Code Online (Sandbox Code Playgroud)

然后你可以做一个单独的文本替换,在继续创建imagick jpeg/png之前将css规则注入svg.如果颜色没有变化,请检查以确保路径标记中没有任何内联填充样式覆盖css.

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

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

然后改变颜色就像:

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

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

Spu*_*ley 11

你提到你这样做是因为IE不支持SVG.

好消息是IE 确实支持矢量图形.好吧,所以它是一种叫做VML的语言形式,只有IE支持,而不是SVG,但它就在那里,你可以使用它.

除其他外,谷歌地图将检测浏览器功能,以确定是否提供SVG或VML.

然后是Raphael库,这是一个基于Javascript browswer的图形库,它支持SVG或VML,同样取决于浏览器.

另一个可能有用的:SVGWeb.

所有这些都意味着您可以支持您的IE用户,而无需使用位图图形.

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


psy*_*brm 8

将SVG转换为透明PNG时,别忘了把它放在$ imagick-> readImageBlob()之前:

$imagick->setBackgroundColor(new ImagickPixel('transparent'));
Run Code Online (Sandbox Code Playgroud)


小智 6

这很容易,过去几周一直在做这方面的工作.

你需要Batik SVG工具包.下载并将文件放在与要转换为JPEG的SVG相同的目录中,同时确保先将其解压缩.

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

java -jar batik-rasterizer.jar -m image/jpeg -q 0.8 NAME_OF_SVG_FILE.svg
Run Code Online (Sandbox Code Playgroud)

那应该输出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')
Run Code Online (Sandbox Code Playgroud)


ole*_*lin 5

这是使用标准 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>    
Run Code Online (Sandbox Code Playgroud)

然后在服务器(ProcessPicture.php)中将其从(默认)png 转换为 gif 并保存。(你也可以保存为 png,然后使用 imagepng 而不是图像 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);
Run Code Online (Sandbox Code Playgroud)

  • 我支持这个答案,因为它是唯一真正适用于更复杂的 SVG 图像的 PHP 解决方案。所有图书馆,包括。Imagick 因渲染错误而失败。该解决方案很复杂,但可以自动化并且具有最佳结果。 (2认同)