Convertir SVG image en PNG avec PHP
je travaille sur un projet web qui implique une carte générée dynamiquement des États américains colorant différents états basés sur un ensemble de données.
Ce SVG fichier me donne une bonne carte vierge de la de NOUS et il est très facile de changer la couleur de chaque état. La difficulté est que les navigateurs IE ne prennent pas SVG en charge, donc pour que je puisse utiliser la syntaxe pratique offerte par svg, je vais avoir besoin de le convertir en JPG.
idéalement, j'aimerais pour ce faire, utilisez uniquement la bibliothèque GD2, mais aussi ImageMagick. Je n'ai absolument aucune idée de comment faire cela.
toute solution qui me permettrait de changer dynamiquement les couleurs des États sur une carte des États-Unis sera considérée. La clé, c'est qu'il est facile de changer les couleurs à la volée et qu'il est de la croix-navigateur. PHP/Apache solutions seulement, s'il vous plaît.
10 réponses
c'est marrant que vous me demandiez ça, je viens de le faire récemment pour le site de mon travail et je pensais que je devrais écrire un tutoriel... Voici comment le faire avec PHP / Imagick, qui utilise 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();
les étapes de remplacement de couleur regex peut varier en fonction du chemin de svg xml et de la façon dont vous id et les valeurs de couleur sont stockées. Si vous ne voulez pas stocker un fichier sur le serveur, vous pouvez afficher l'image comme base 64 comme
<?php echo '<img src="data:image/jpg;base64,' . base64_encode($im) . '" />';?>
(avant utilisez clear/destroy) mais ie a des problèmes avec PNG comme base64 donc vous devriez probablement sortir base64 comme jpeg
vous pouvez voir un exemple ici que j'ai fait pour le territoire de vente d'un ancien employeur carte:
Début: /images/contenu/4809194/54a799ea27317e1b044ab95038b2e98b.svg
finition:
Modifier
depuis que j'ai écrit ce qui précède, j'ai trouvé 2 techniques améliorées:
1) au lieu d'une boucle regex pour changer l'état fill on, utilisez CSS pour faire des règles de style comme
<style type="text/css">
#CA,#FL,HI{
fill:blue;
}
#Al, #NY, #NM{
fill:#cc6699;
}
/*etc..*/
</style>
et ensuite vous pouvez faire un simple remplacement de texte pour injecter vos règles css dans le svg avant de procéder à la création d'imagick jpeg/png. Si les couleurs ne changent pas, vérifiez que vous n'en avez pas remplissez les styles en ligne dans vos balises de chemin qui supplantent le css.
2) Si vous n'avez pas à créer un fichier image jpeg/png (et n'avez pas besoin de prendre en charge des navigateurs obsolètes), vous pouvez manipuler le svg directement avec jQuery. Vous ne pouvez pas accéder aux chemins svg lors de l'intégration du svg en utilisant des balises IMG ou object, vous devrez donc inclure directement le xml svg dans votre page Web html comme:
<div>
<?php echo file_get_contents('/path/to/blank/us-map.svg');?>
</div>
puis changer les couleurs est aussi facile que:
<script type="text/javascript" src="/path/to/jquery.js"></script>
<script type="text/javascript">
$('#CA').css('fill', 'blue');
$('#NY').css('fill', '#ff0000');
</script>
une autre option très rapide et précise est le navigateur sans tête PhantomJS (webkit)
vous mentionnez que vous faites cela parce que IE ne supporte pas SVG.
la bonne nouvelle, C'est QU'IE fait supporte les graphiques vectoriels. Ok, donc c'est sous la forme d'un langage appelé VML qui ne supporte QU'IE, plutôt que SVG, mais il est là, et vous pouvez l'utiliser.
Google Maps, entre autres, détectera les capacités du navigateur pour déterminer si servir SVG ou VML.
puis il y a le Bibliothèque Raphael , qui est une bibliothèque graphique basée sur browswer Javascript, qui prend en charge SVG ou VML, encore une fois en fonction du navigateur.
un Autre qui peut aider: SVGWeb .
ce qui signifie que vous pouvez prendre en charge vos utilisateurs IE sans avoir à recourir à des graphiques bitmap.
Voir aussi la réponse du haut à cette question, par exemple: xsl Transform SVG to VML
lors de la conversion de SVG en PNG transparent, n'oubliez pas de mettre ceci avant $ imagick- > readImageBlob ():
$imagick->setBackgroundColor(new ImagickPixel('transparent'));
ici v. easy, nous y travaillons depuis quelques semaines.
Vous avez besoin de la Batik SVG boîte à outils . Télécharger , et placer les fichiers dans le même répertoire que le SVG que vous voulez convertir en JPEG , assurez-vous également de décompresser d'abord.
Ouvrez le terminal et exécutez cette commande:
java -jar batik-rasterizer.jar -m image/jpeg -q 0.8 NAME_OF_SVG_FILE.svg
qui devrait sortir un JPEG du fichier SVG. Vraiment facile. Vous peut même simplement le placer dans une boucle et convertir des charges de 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')
vous pouvez utiliser la bibliothèque canvg js pour convertir le SVG en PNG, plus d'informations ici http://paksula.users.cs.helsinki.fi/svg_open_2010/demo.xhtml compatible avec tous les principaux navigateurs!
Je l'utilise dans mon projet et convertit effectivement le SVG en PNG (avec L'aide de PHP pour enregistrer le fichier Bien sûr)
Je ne connais pas de solution PHP / Apache autonome, car cela nécessiterait une bibliothèque PHP capable de lire et de rendre des images SVG. Je ne suis pas sûr qu'une telle bibliothèque existe - je n'en connais aucune.
ImageMagick est capable de rastérider des fichiers SVG, soit à travers la ligne de commande ou la liaison PHP, IMagick , mais semble avoir un certain nombre de bizarreries et de dépendances externes comme indiqué par exemple dans ce fil de forum . Je pense que c'est la façon la plus prometteuse d'y aller, c'est la première chose que je verrais si j'étais vous.
$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);
ou en utilisant: potrace Démo: Tool4dev.com
il s'agit d'une méthode pour convertir une image svg en gif en utilisant les outils standard de php GD
1) vous mettez l'image dans un élément de toile dans le navigateur:
<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>
et ensuite le convertir au serveur (ProcessPicture.php) à partir de (par défaut), le format png de gif et de l'enregistrer. (vous auriez pu sauvegarder en png aussi alors utiliser imagepng au lieu de 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);
vous pouvez utiliser Raphaël-bibliothèque JavaScript et le réaliser facilement. Cela fonctionnera aussi dans IE.