Преобразование SVG изображения в PNG с помощью PHP
Я работаю над веб-проектом, который включает динамически генерируемую карту США, раскрашивающую различные штаты на основе набора данных.
Этот файл SVG дает мне хорошую пустую карту США и очень легко изменить цвет каждого штата. Сложность заключается в том, что браузеры IE не поддерживают SVG, поэтому для того, чтобы я мог использовать удобный синтаксис svg, мне нужно преобразовать его в JPG.
В идеале я хотел бы сделать это только с библиотекой GD2, но также мог бы использовать ImageMagick. Я понятия не имею, как это сделать.
Будет рассмотрено любое решение, которое позволило бы мне динамически изменять цвета Штатов на карте США. Ключ в том, что это легко изменить цвета на лету и что это кросс-браузер. Только PHP / Apache решения, пожалуйста.
10 ответов:
Забавно, что вы спросили об этом, я только недавно сделал это для сайта моей работы, и я думал, что должен написать учебник... Вот как это сделать с 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 и способа хранения значений идентификатора и цвета. Если вы не хотите хранить файл на сервере, вы можете вывести изображение в виде базы 64, например
<?php echo '<img src="data:image/jpg;base64,' . base64_encode($im) . '" />';?>(Перед использованием clear / destroy) но ie имеет проблемы с PNG как base64, так что вам, вероятно, придется вывести base64 как jpeg
Здесь вы можете увидеть пример, который я сделал для карты территории продаж бывшего работодателя:Начало: /изображение/содержание/4809194/54a799ea27317e1b044ab95038b2e98b.СВГ
Финиш:
править
С момента написания вышеизложенного я придумал 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 или 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>
Вы упомянули, что делаете это, потому что IE не поддерживает SVG.
Хорошей новостью является то, что IE поддерживает векторную графику. Хорошо, это в виде языка под названием VML, который поддерживает только IE, а не SVG, но он есть, и вы можете его использовать.Google Maps, среди прочего, определит возможности браузера, чтобы определить, следует ли обслуживать SVG или VML.
, то есть Рафаил библиотека, который является JavaScript browswer-графики библиотека, которая поддерживает либо SVG, либо VML, опять же в зависимости от браузера.
Еще один, который может помочь: SVGWeb .
Все это означает, что вы можете поддерживать своих пользователей IE, не прибегая к растровой графике.
Смотрите также верхний ответ на этот вопрос, например: xsl Transform SVG to VML
При преобразовании SVG в прозрачный PNG, не забудьте поставить это перед $imagick - >readImageBlob ():
$imagick->setBackgroundColor(new ImagickPixel('transparent'));
Это В. легко, я работаю над этим в течение последних нескольких недель.
Вам понадобится Batik SVG Toolkit. Загрузите иПоместите файлы в тот же каталог, что и SVG, который вы хотите преобразовать в JPEG , также убедитесь, что вы сначала распакуете его.
Откройте терминал и выполните следующую команду:
java -jar batik-rasterizer.jar -m image/jpeg -q 0.8 NAME_OF_SVG_FILE.svgЭто должно вывести JPEG файла SVG. Действительно простой. Вы даже можете просто поместить его в цикл и преобразовать нагрузки SVGs,
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 демо : Tool4dev.com
Это метод преобразования svg-изображения в gif с использованием стандартных инструментов 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);
Вы можете использовать библиотеку Raphaël-JavaScript и легко достичь этого. Он будет работать и в IE.

Comments