it-roy-ru.com

Конвертировать SVG изображение в PNG с PHP

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

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

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

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

98
Michael Berkompas

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

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

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

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

Конец: 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>
128
WebChemist

Еще одна очень быстрая и точная опция - браузер без головы PhantomJS (webkit)

http://phantomjs.org/

17
atomicjeep

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

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

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

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

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

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

Смотрите также лучший ответ на этот вопрос, например: XSL Transform SVG to VML

11
Spudley

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

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

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

Вам нужен 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')
6
user179169

вы можете использовать библиотеку canvg js для конвертирования SVG в PNG, подробнее здесь http://paksula.users.cs.helsinki.fi/svg_open_2010/demo.xhtml совместим со всеми основными браузерами!

Я использую его в своем проекте и фактически конвертирую SVG в PNG (конечно, с помощью PHP, чтобы сохранить файл)

3
razor7

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

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

2
Pekka 웃

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

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);
0
oleviolin