PHPでSVG画像をPNGに変換


111

私は、データのセットに基づいてさまざまな州を着色する米国の動的に生成されたマップを含むWebプロジェクトに取り組んでいます。

この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を使用する前)しかし、つまりbase64としてのPNGに問題があるため、おそらく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タグまたはオブジェクトタグを使用してsvgを埋め込む場合、svgパスにアクセスできないため、次のようにWebページの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はIE8以下ではサポートされておらず、ユーザーがSVGビューアプラグインをインストールする必要はありません。 3] Internet Explorer 9ベータ版は、基本的なSVG機能セットをサポートしています。[4]現在、Androidで実行されているブラウザのサポートも制限されています。」
WebChemist 2011年

1
はい、しかしsvgwebは少し​​のjsとflashを使用してすべての非互換性を解決するようです。それが私が行った解決策です。
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();
2012年

xmlパーサーは他のsvgと比べて少し遅いですが、安全です。この場合、各州の属性が(id = "XX" style = "fill:# XXXXXX」)。
WebChemist 2012年

11

IEはSVGをサポートしていないため、これを行っていると述べています。

良いニュースは、IE ベクターグラフィックスをサポートしていることです。さて、それはSVGではなく、IEのみがサポートするVMLと呼ばれる言語の形式ですが、そこにあり、使用できます。

特にGoogleマップは、ブラウザ機能を検出して、SVGとVMLのどちらを提供するかを決定します。

次に、Raphaelライブラリがあります。これは、ブラウザに応じて、SVGまたはVMLのいずれかをサポートするJavaScriptのブラウザベースのグラフィックライブラリです。

助けるかもしれないもう一つ:SVGWeb

つまり、ビットマップグラフィックスに頼ることなく、IEユーザーをサポートできます。

この質問のトップアンサーも参照してください。例:XSL変換SVGからVML


+1はラファエルについて言及している。これは間違いなく優れたソリューションであり、クロスブラウザーのベクターグラフィックスの優れた実装について調査する価値があります。
dmp、2011年

10

SVGを透明なPNGに変換するときは、これをBEFOREの前に置くことを忘れないでください$imagick->readImageBlob()

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

画像を読み取る前にそのメソッドを呼び出すことはどうして可能ですか、「空のImagickオブジェクトを処理できません」というエラーを受け取ります。そして、はい、画像が機能し変換されているので、私のimagick拡張機能がインストールされています。
Denis2310

6

これは簡単です。過去数週間、これに取り組んできました。

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

これは素晴らしい。先端をありがとう。これをperlと組み合わせて使用​​して、テンプレートから作成したSVGファイルのロードをバッチ処理します。
シンバベク

2

スタンドアロンのPHP / Apacheソリューションについては知りません。これには、SVG画像を読み取ってレンダリングできるPHPライブラリが必要になるためです。そのようなライブラリが存在するかどうかはわかりません-わかりません。

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に変換して保存します。(あなたもpngとして保存し、image gifの代わりにimagepngを使用することができます):

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