繁体   English   中英

使用 PHP 将 SVG 图像转换为 PNG

[英]Convert SVG image to PNG with PHP

我正在研究一个 web 项目,该项目涉及一个动态生成的美国 map 根据一组数据着色不同的州。

这个 SVG 文件给了我一个很好的空白 map 并且很容易改变每个 state 的颜色。 困难在于 IE 浏览器不支持 SVG 所以为了让我使用 svg 提供的方便语法,我需要将其转换为 JPG。

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

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

你问这个问题很有趣,我最近刚刚为我的工作网站做了这个,我想我应该写一个教程......这里是如何使用 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 之前)但 IE 有问题,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>

然后你可以做一个单一的文本替换,在继续创建 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>

那么改变颜色就像这样简单:

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

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

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

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

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

除其他外,Google Maps 将检测浏览器功能,以确定是提供 SVG 还是 VML。

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

另一个可能有帮助的: SVGWeb

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

另请参阅此问题的最佳答案,例如: XSL Transform SVG to VML

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

您需要Batik SVG Toolkit 下载并将文件放在与要转换为 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')

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

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>    

然后在服务器 (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);

我不知道独立的 PHP/Apache 解决方案,因为这需要一个可以读取和渲染 SVG 图像的 PHP 库。 我不确定这样的图书馆是否存在——我不知道。

ImageMagick能够通过命令行或 PHP 绑定IMagick对 SVG 文件进行光栅化,但似乎有许多怪癖和外部依赖项,例如本论坛帖子中所示 我认为这仍然是最有前途的方式,如果我是你,这是我首先考虑的事情。

我也想分享我的答案,它可能会对某人有所帮助。

当您 svg 不包含填充样式且默认情况下为黑色并且您希望将其转换为 png 并为结果 png 添加颜色时,这更适用于简单的情况。

function convertSvgToPng($svgPath, $fillColor, $outPath)
{
    $im = new Imagick();
    $svg = file_get_contents($svgPath);
    
    // !!! THIS is the trick part - just appending to all <path fill color
    $svg = str_replace('<path ', '<path style="fill:'.$fillColor.'" ', $svg);
    
    $im->readImageBlob($svg);       
    $im->setImageFormat("png24");

    $im->writeImage($outPath);
    $im->clear();
    $im->destroy();
}

您可以使用Raphaël—JavaScript 库并轻松实现。 它也适用于 IE。

$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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM