Преобразование SVG-изображения в PNG с помощью PHP

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

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

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

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

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

замена цвета регулярных выражений шагов может варьироваться в зависимости от пути xvg path и как вы сохраняете значения идентификатора и цвета. Если вы не хотите хранить файл на сервере, вы можете выводить изображение в качестве базы 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

Конец: введите описание изображения здесь

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

Начиная с написания выше, я придумал 2 улучшенных метода:

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

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

и затем вы можете сделать один текст, чтобы вставлять ваши правила css в svg, прежде чем приступать к созданию jpeg / png imagick. Если цвета не меняются, убедитесь, что у вас нет встроенных стилей заливки в тегах пути, переопределяющих css.

2) Если вам не нужно создавать файл jpeg / png (и не нужно поддерживать устаревшие браузеры), вы можете напрямую управлять svg с помощью jQuery. Вы не можете получить доступ к SVG-тропам при встраивании svg с использованием тегов img или object, поэтому вам нужно будет напрямую включить 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> 

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

http://phantomjs.org/

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

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

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

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

Другая, которая может помочь: SVGWeb .

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

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

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

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

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

Вам нужен набор инструментов Batik SVG . Загрузите и поместите файлы в тот же каталог, что и 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') 

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

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

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

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

 $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

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