首页 文章

使用PHP将SVG图像转换为PNG

提问于
浏览
99

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

这个SVG文件给了我一张很好的美国空白 Map ,很容易改变每个州的颜色 . 困难在于IE浏览器不需要将其转换为JPG .

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

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

10 回答

  • 8

    另一个非常快速和准确的选择是无头浏览器PhantomJS(webkit)

    http://phantomjs.org/

  • 11

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

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

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

    完成:
    enter image description here

    Edit

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

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

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

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

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

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

    另一个可能会有所帮助:SVGWeb .

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

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

  • 2

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

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

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

    你需要Batik SVG Toolkit . 下载和 place the files in the same directory as the SVG you want to convert to a JPEG ,还要确保先解压缩 .

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

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

    你可以使用canvg js库将SVG转换为PNG,更多信息在这里http://paksula.users.cs.helsinki.fi/svg_open_2010/demo.xhtml与所有主流浏览器兼容!

    我在我的项目中使用它并实际将SVG转换为PNG(当然,在PHP的帮助下保存文件)

  • 0

    我不知道独立的PHP / Apache解决方案,因为这需要一个可以读取和呈现SVG图像的PHP库 . 我不确定这样的图书馆存在 - 我不知道 .

    ImageMagick能够通过命令行或PHP绑定来光栅化SVG文件,但似乎有许多怪癖和外部依赖关系,例如:在this forum thread . 如果我是你,我认为这是我要研究的第一件事 .

  • 129

    这是一种使用标准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而不是图像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);
    
  • 3

    您可以使用Raphaël—JavaScript Library轻松实现 . 它也适用于IE .

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

相关问题