Конвертировать SVG-изображение в PNG с PHP - PullRequest
100 голосов
/ 26 января 2011

Я работаю над веб-проектом, который включает в себя динамически генерируемую карту США, раскрашивающую разные штаты на основе набора данных.

Этот файл SVG дает мне хорошую пустую карту США и очень легко изменить цвет каждого штата.Сложность в том, что браузеры IE не поддерживают SVG, поэтому для того, чтобы я использовал удобный синтаксис, предлагаемый svg, мне нужно преобразовать его в JPG.

В идеале я хотел бы сделать это только с библиотекой GD2, но также мог бы использовать ImageMagick.Я понятия не имею, как это сделать.

Будет рассмотрено любое решение, которое позволило бы мне динамически изменять цвета штатов на карте США.Ключевым моментом является то, что это легко изменить цвета на лету, и это кросс-браузер.Только для PHP / Apache, пожалуйста.

Ответы [ 8 ]

132 голосов
/ 26 января 2011

Забавно, что вы спросили об этом, я недавно сделал это для сайта своей работы и подумал, что мне следует написать учебник ... Вот как это сделать с помощью 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();

этапы замены цвета регулярного выражения могут различаться в зависимости от XML-пути svg и того, как хранятся ваши значения идентификатора и цвета.Если вы не хотите сохранять файл на сервере, вы можете вывести изображение в формате base 64, например

<?php echo '<img src="data:image/jpg;base64,' . base64_encode($im) . '"  />';?>

(до того, как вы используете очистить / уничтожить), но у вас есть проблемы с PNG в качестве base64, так что выВам, вероятно, придется вывести base64 в формате jpeg

, здесь вы можете увидеть пример, который я сделал для карты территории продаж бывшего работодателя:

Начало: https://upload.wikimedia.org/wikipedia/commons/1/1a/Blank_US_Map_(states_only).svg

image

Finish: enter image description here

Редактировать

С момента написания вышеизложенного я придумал 2 улучшенных метода:

1) вместо цикла регулярных выражений, чтобы изменить состояние заполнения, используйте CSS для создания правил стиля, таких как

<style type="text/css">
#CA,#FL,HI{
    fill:blue;
}
#Al, #NY, #NM{
    fill:#cc6699;
}
/*etc..*/
</style>

, а затем вы можете сделать одну замену текста, чтобы вставить ваши правила CSS в SVG перед тем, как продолжитьсоздание Imagick JPEG / PNG.Если цвета не меняются, убедитесь, что у вас нет встроенных стилей заливки в ваших тегах пути, перекрывающих CSS.

2) Если вам не нужно создавать jpeg / pngфайл изображения (и не нужно поддерживать устаревшие браузеры), вы можете напрямую управлять svg с помощью jQuery.Вы не можете получить доступ к путям svg при встраивании svg с помощью img или тегов объекта, поэтому вам нужно будет напрямую включить svg xml в html вашей веб-страницы, например:

<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>
11 голосов
/ 26 января 2011

Вы упоминаете, что делаете это, потому что IE не поддерживает SVG.

Хорошей новостью является то, что IE поддерживает векторную графику. Итак, это в форме языка VML, который поддерживает только IE, а не SVG, но он есть, и вы можете его использовать.

Карты Google, среди прочего, обнаружат возможности браузера, чтобы определить, обслуживать ли SVG или VML.

Затем есть библиотека Raphael , которая является графической библиотекой на основе браузера Javascript, которая поддерживает SVG или VML, опять же, в зависимости от браузера.

Еще один, который может помочь: SVGWeb .

Все это означает, что вы можете поддерживать своих пользователей IE без необходимости прибегать к растровой графике.

См. Также главный ответ на этот вопрос, например: XSL Преобразование SVG в VML

8 голосов
/ 21 ноября 2012

При преобразовании SVG в прозрачный PNG, не забудьте поставить это ПЕРЕД $ imagick-> readImageBlob ():

$imagick->setBackgroundColor(new ImagickPixel('transparent'));
6 голосов
/ 26 января 2011

Это очень просто, я работал над этим в течение последних нескольких недель.

Вам необходим Batik SVG Toolkit . Загрузите и поместите файлы в тот же каталог, что и SVG, который вы хотите преобразовать в JPEG , также сначала обязательно разархивируйте его.

Откройте терминал и выполните эту команду:

java -jar batik-rasterizer.jar -m image/jpeg -q 0.8 NAME_OF_SVG_FILE.svg

Это должно вывести JPEG файла SVG. Действительно легко. Вы даже можете просто поместить его в цикл и преобразовать множество 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')
2 голосов
/ 26 января 2011

Я не знаю отдельного решения PHP / Apache, так как для этого потребовалась бы библиотека PHP, которая может читать и визуализировать изображения SVG. Я не уверен, что такая библиотека существует - я не знаю ни одной.

ImageMagick может растеризовать SVG-файлы либо через командную строку, либо с помощью привязки PHP, IMagick , но, похоже, имеет ряд причуд и внешних зависимостей, как показано, например, в этой теме форума . Я думаю, что это все еще самый многообещающий путь, это первое, на что я бы посмотрел, если бы я был тобой.

1 голос
/ 31 мая 2018

Это метод для преобразования изображения SVG в рисунок с использованием стандартных инструментов php GD

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 вместо 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);
0 голосов
/ 07 октября 2015
$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 demo: Tool4dev.com

0 голосов
/ 14 августа 2014

Вы можете использовать Raphaël — JavaScript Library и легко достичь этого. Это будет работать и в IE.

...