developer tip

PHP를 사용하여 SVG 이미지를 PNG로 변환

optionbox 2020. 8. 15. 09:05
반응형

PHP를 사용하여 SVG 이미지를 PNG로 변환


저는 데이터 세트를 기반으로 여러 주를 채색하는 동적으로 생성 된 미국지도를 포함하는 웹 프로젝트를 진행하고 있습니다.

이 SVG 파일은 미국의 좋은 빈지도를 제공하며 각주의 색상을 변경하기 매우 쉽습니다. 어려움은 IE 브라우저가 SVG를 지원하지 않기 때문에 SVG가 제공하는 편리한 구문을 사용하려면 JPG로 변환해야합니다.

이상적으로는 GD2 라이브러리로만이 작업을 수행하고 싶지만 ImageMagick을 사용할 수도 있습니다. 이 작업을 수행하는 방법에 대한 단서가 전혀 없습니다.

미국지도에서 주 색상을 동적으로 변경할 수있는 모든 솔루션이 고려됩니다. 핵심은 즉석에서 색상을 변경하기 쉽고 크로스 브라우저라는 것입니다. PHP / Apache 솔루션 만 사용하십시오.


재밌군요. 최근에 제 작업 사이트에서이 작업을 수행했고 튜토리얼을 작성해야한다고 생각했습니다 ... ImageMagick을 사용하는 PHP / Imagick으로 수행하는 방법은 다음과 같습니다.

$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

끝: enter image description here

편집하다

위의 글을 쓴 이후로 두 가지 개선 된 기술을 생각해 냈습니다.

1) instead of a regex loop to change the fill on state , use CSS to make style rules like

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

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:

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

You mention that you are doing this because IE doesn't support SVG.

The good news is that IE does support 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.

Google Maps, among others, will detect the browser capabilities to determine whether to serve SVG or 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.

Another one which may help: SVGWeb.

All of which means that you can support your IE users without having to resort to bitmap graphics.

See also the top answer to this question, for example: XSL Transform SVG to VML


When converting SVG to transparent PNG, dont forget to put this BEFORE $imagick->readImageBlob():

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

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.

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,

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

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.

ImageMagick is 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.


This is a method for converting a svg picture to a gif using standard php GD tools

1) You put the image into a canvas element in the browser:

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

//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);

You can use Raphaël—JavaScript Library and achieve it easily. It will work in IE also.


$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

참고URL : https://stackoverflow.com/questions/4809194/convert-svg-image-to-png-with-php

반응형