使用 PHP 将 SVG 图像转换为 PNG
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4809194/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Convert SVG image to PNG with PHP
提问by Michael Berkompas
I'm working on a web project that involves a dynamically generated map of the US coloring different states based on a set of data.
我正在开发一个 Web 项目,该项目涉及基于一组数据为不同州着色的动态生成的美国地图。
This SVG file gives me a good blank map of the US and is very easy to change the color of each state. The difficulty is that IE browsers don't support SVG so in order for me to use the handy syntax the svg offers, I'll need to convert it to a JPG.
这个 SVG 文件给了我一张很好的美国空白地图,而且很容易改变每个州的颜色。困难在于 IE 浏览器不支持 SVG,所以为了让我使用 svg 提供的方便语法,我需要将其转换为 JPG。
Ideally, I'd like to do this with only the GD2 library but could also use ImageMagick. I have absolutely no clue how to do this.
理想情况下,我只想使用 GD2 库执行此操作,但也可以使用 ImageMagick。我完全不知道如何做到这一点。
Any solution that would allow me to dynamically change the colors of states on a map of the US will be considered. The key is that it is easy to change the colors on the fly and that it is cross browser. PHP/Apache solutions only, please.
任何允许我动态更改美国地图上各州颜色的解决方案都将被考虑。关键是很容易即时更改颜色,而且它是跨浏览器的。请仅使用 PHP/Apache 解决方案。
回答by WebChemist
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:
你问这个问题很有趣,我最近刚刚为我的工作网站做了这个,我想我应该写一个教程......这里是如何使用 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();
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
正则表达式颜色替换的步骤可能会因 svg 路径 xml 以及您的 id 和颜色值的存储方式而异。如果您不想在服务器上存储文件,则可以将图像输出为 base 64,如
<?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
(在使用 clear/destroy 之前)但 IE 有问题,PNG 为 base64,因此您可能必须将 base64 输出为 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
开始:https: //upload.wikimedia.org/wikipedia/commons/1/1a/Blank_US_Map_(states_only).svg
Finish:
结束:
Edit
编辑
Since writing the above, I've come up with 2 improved techniques:
自从写完上面的内容后,我提出了 2 个改进的技术:
1) instead of a regex loop to change the fill on state , use CSS to make style rules like
1) 而不是正则表达式循环来改变状态的填充,使用 CSS 来制作样式规则,如
<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.
然后你可以做一个单一的文本替换,在继续创建 imagick jpeg/png 之前将你的 css 规则注入到 svg 中。如果颜色没有改变,请检查以确保您的路径标签中没有任何覆盖 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:
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>
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>
回答by Spudley
You mention that you are doing this because IE doesn't support SVG.
您提到您这样做是因为 IE 不支持 SVG。
The good news is that IE doessupport 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.
好消息是 IE确实支持矢量图形。好的,所以它是一种叫做 VML 的语言,它只支持 IE,而不是 SVG,但它就在那里,你可以使用它。
Google Maps, among others, will detect the browser capabilities to determine whether to serve SVG or VML.
除其他外,Google Maps 将检测浏览器功能,以确定是提供 SVG 还是 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.
然后是Raphael 库,它是一个基于 Javascript 浏览器的图形库,它支持 SVG 或 VML,同样取决于浏览器。
Another one which may help: SVGWeb.
另一个可能有帮助的:SVGWeb。
All of which means that you can support your IE users without having to resort to bitmap graphics.
所有这些都意味着您可以支持您的 IE 用户,而不必求助于位图图形。
See also the top answer to this question, for example: XSL Transform SVG to VML
另请参阅此问题的最佳答案,例如:XSL Transform SVG to VML
回答by psycho brm
When converting SVG to transparent PNG, don't forget to put this BEFORE $imagick->readImageBlob()
:
将 SVG 转换为透明 PNG 时,不要忘记将其放在 BEFORE 之前$imagick->readImageBlob()
:
$imagick->setBackgroundColor(new ImagickPixel('transparent'));
回答by psycho brm
This is v. easy, have been doing work on this for the past few weeks.
这很容易,过去几周一直在做这方面的工作。
You need the Batik SVG Toolkit. Download, and place the files in the same directory as the SVG you want to convert to a JPEG, also make sure you unzip it first.
您需要Batik SVG Toolkit。下载并将文件放在与要转换为 JPEG 的 SVG 相同的目录中,还要确保先将其解压缩。
Open the terminal, and run this command:
打开终端,然后运行以下命令:
java -jar batik-rasterizer.jar -m image/jpeg -q 0.8 NAME_OF_SVG_FILE.svg
That should output a JPEG of the SVG file. Really easy. You can even just place it in a loop and convert loads of SVGs,
那应该输出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')
回答by Pekka
I do not know of a standalone PHP / Apache solution, as this would require a PHP library that can read and render SVG images. I'm not sure such a library exists - I don't know any.
我不知道独立的 PHP/Apache 解决方案,因为这需要一个可以读取和渲染 SVG 图像的 PHP 库。我不确定这样的图书馆是否存在——我不知道。
ImageMagickis able to rasterize SVG files, either through the command line or the PHP binding, IMagick, but seems to have a number of quirks and external dependencies as shown e.g. in this forum thread. I think it's still the most promising way to go, it's the first thing I would look into if I were you.
ImageMagick能够光栅化 SVG 文件,无论是通过命令行还是 PHP 绑定,IMagick,但似乎有许多怪癖和外部依赖关系,例如在这个论坛线程中所示。我认为这仍然是最有前途的方式,如果我是你,这是我首先考虑的事情。
回答by oleviolin
This is a method for converting a svg picture to a gif using standard php GD tools
这是一种使用标准php GD工具将svg图片转换为gif的方法
1) You put the image into a canvas element in the browser:
1)您将图像放入浏览器中的画布元素中:
<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>
And then convert it at the server (ProcessPicture.php) from (default) png to gif and save it. (you could have saved as png too then use imagepng instead of image gif):
然后在服务器 (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);
回答by Lokesh Kumar Ravi
You can use Rapha?l—JavaScript Libraryand achieve it easily. It will work in IE also.
您可以使用Rapha?l—JavaScript 库并轻松实现它。它也适用于 IE。
回答by Thành NV
$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);
or using : potrace demo :Tool4dev.com
或使用:potrace 演示:Tool4dev.com