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


111

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

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

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

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


SVG를 VML로 포팅하도록 설계된 클래스가 있습니까? 그렇게하면 여전히 'HTML5'유형의 솔루션을 가질 수 있습니다.
Patrick

내 대답을 살펴보십시오. 정확히 필요한 것

답변:


142

당신이 이것을 물었다는 것은 재밌습니다. 저는 최근에 제 작업 사이트를 위해 이것을했습니다. 그리고 저는 튜토리얼을 작성해야한다고 생각하고있었습니다 ... 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

끝: 여기에 이미지 설명 입력

편집하다

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

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>

1
이를 수행하는 방법에 대한 매우 정확하고 유용한 튜토리얼에 감사드립니다. 나는 확실히 당신의 솔루션을 백업으로 사용할 것이지만 모든 주요 브라우저에서 svg 호환성을 얻으려고 노력하고 있습니다.
Michael Berkompas 2011 년

1
SVG는 사용자가 SVG 뷰어 플러그인을 설치하지 않아도 ie8 이하에서 지원되지 않습니다.-SVG Wikipedia 페이지에서 : "모든 주요 최신 웹 브라우저, Microsoft Internet Explorer (IE)의 매우 주목할만한 예외를 제외하고 직접 SVG 마크 업을 지원 및 렌더링합니다. 3] Internet Explorer 9 베타는 기본 SVG 기능 세트를 지원합니다. [4] 현재 Android에서 실행되는 브라우저에 대한 지원도 제한되어 있습니다. "
WebChemist 2011 년

1
예,하지만 svgweb은 약간의 js와 플래시를 사용하여 모든 비 호환성을 해결하는 것 같습니다. 그것이 제가 함께했던 해결책입니다.
Michael Berkompas 2011 년

2
나는 당신의 깨끗하고 빠른 솔루션을 좋아합니다. 개인적으로 xml 파일과 상호 작용할 때 정규식보다 안전하다고 느끼기 위해 dom 파서를 사용하는 것을 선호합니다. Sth like :$dom = new DOMDocument(); $dom->loadXML( $svg ); $dom->getElementsByTagName('image')->item(0)->setAttribute('id', $state); $svg = $dom->saveXML();
Tapper

xml 파서는 더 안전하지만 약간 더 느리지 만 다른 svg를 사용하는 솔루션입니다.이 경우 정규식은 각 상태의 속성이 (id = "XX"style = "fill : # XXXXXX ").
WebChemist 2010 년

11

IE가 SVG를 지원하지 않기 때문에이 작업을 수행한다고 언급했습니다.

좋은 소식은 IE 벡터 그래픽을 지원 한다는 것 입니다. 좋습니다. 이것은 SVG가 아닌 IE 만 지원하는 VML이라는 언어의 형태이지만 거기에 있고 사용할 수 있습니다.

무엇보다도 Google지도는 브라우저 기능을 감지하여 SVG 또는 VML을 제공할지 여부를 결정합니다.

그 다음에 는 브라우저에 따라 SVG 또는 VML을 지원하는 자바 스크립트 브라우저 기반 그래픽 라이브러리 인 Raphael 라이브러리 가 있습니다.

도움이 될 수있는 또 다른 방법 : SVGWeb .

즉, 비트 맵 그래픽에 의존하지 않고도 IE 사용자를 지원할 수 있습니다.

이 질문에 대한 상위 답변도 참조하십시오. 예 : XSL SVG를 VML로 변환


확실히 좋은 솔루션이며 크로스 브라우저 벡터 그래픽의 뛰어난 구현에 대해 조사 할 가치가있는 raphael을 언급 한 경우 +1.
dmp

10

SVG를 투명한 PNG로 변환 할 때 다음을 입력하는 것을 잊지 마십시오 $imagick->readImageBlob().

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

이미지를 읽기 전에 어떻게 그 메서드를 호출 할 수 있습니까? "빈 Imagick 개체를 처리 할 수 ​​없습니다"라는 오류 메시지가 나타납니다. 그리고 예, imagick 확장 프로그램이 작동하고 이미지를 변환하면서 설치됩니다.
Denis2310

6

이것은 v. 쉽습니다. 지난 몇 주 동안 이것에 대한 작업을 해왔습니다.

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

이것은 훌륭합니다. 팁 고마워. 템플릿에서 만든 SVG 파일로드를 일괄 처리하기 위해 perl과 함께 사용할 것입니다.
simbabque

2

SVG 이미지를 읽고 렌더링 할 수있는 PHP 라이브러리가 필요하기 때문에 독립 실행 형 PHP / Apache 솔루션을 모릅니다. 그런 라이브러리가 있는지 잘 모르겠습니다. 저는 어떤 것도 모릅니다.

ImageMagick 은 명령 줄이나 PHP 바인딩 IMagick을 통해 SVG 파일을 래스터화할 수 있지만 이 포럼 스레드 에 표시된 것처럼 여러 가지 단점과 외부 종속성이있는 것 같습니다 . 여전히 가장 유망한 방법이라고 생각합니다. 제가 당신이라면 가장 먼저 살펴볼 것입니다.


2

표준 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로 변환하고 저장합니다. (이미지 gif 대신 imagepng를 사용하여 png로 저장할 수도 있습니다) :

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


-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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.