116 votes

Convertir une image SVG en PNG avec PHP

Je travaille sur un projet web qui implique une carte des Etats-Unis générée dynamiquement et colorant différents états en fonction d'un ensemble de données.

Ce fichier SVG me donne une bonne carte vierge des Etats-Unis et il est très facile de changer la couleur de chaque état. La difficulté réside dans le fait que les navigateurs IE ne supportent pas le SVG. Pour pouvoir utiliser la syntaxe pratique du svg, je dois le convertir en JPG.

Idéalement, j'aimerais faire cela avec la seule bibliothèque GD2, mais je pourrais aussi utiliser ImageMagick. Je n'ai absolument aucune idée de la façon de procéder.

Toute solution qui me permettrait de modifier dynamiquement les couleurs des États sur une carte des États-Unis sera prise en considération. L'essentiel est qu'il soit facile de changer les couleurs à la volée et qu'il soit compatible avec tous les navigateurs. Les solutions PHP/Apache uniquement, s'il vous plaît.

0 votes

Existe-t-il des classes conçues pour porter SVG vers VML ? De cette façon, vous pourriez toujours avoir une solution de type 'HTML5'.

0 votes

Jetez un coup d'œil à ma réponse. C'est exactement ce dont vous avez besoin.

153voto

WebChemist Points 2545

C'est drôle que vous demandiez cela, je viens de faire cela 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 du remplacement des couleurs par l'expression rationnelle peuvent varier en fonction du chemin svg xml et de la manière dont les valeurs d'identification et de couleur sont stockées. Si vous ne souhaitez pas stocker un fichier sur le serveur, vous pouvez sortir l'image en base 64 comme suit

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

(avant d'utiliser clear/destroy) mais ie a des problèmes avec les PNG en base64 donc vous devrez probablement sortir en base64 comme jpeg.

Vous pouvez voir ici un exemple que j'ai réalisé pour la carte du territoire de vente d'un ancien employeur :

Commencez : https://upload.wikimedia.org/wikipedia/commons/1/1a/Blank_US_Map_(states_only).svg

Finition : enter image description here

Modifier

Depuis que j'ai écrit ce qui précède, j'ai mis au point deux techniques améliorées :

1) au lieu d'une boucle regex pour changer l'état de remplissage, utilisez les CSS pour établir des règles de style comme suit

<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 du jpeg/png imagick. Si les couleurs ne changent pas, vérifiez que vous n'avez pas de styles de remplissage en ligne dans vos balises path qui remplacent les règles css.

2) Si vous n'avez pas besoin de créer un fichier image jpeg/png (ni de prendre en charge des navigateurs obsolètes), vous pouvez manipuler le svg directement avec jQuery. Vous ne pouvez pas accéder aux chemins d'accès des svg lorsque vous les intégrez à l'aide des balises img ou object, vous devez donc inclure directement le xml du svg dans le html de votre page web :

<div>
<?php echo file_get_contents('/path/to/blank/us-map.svg');?>
</div>

alors changer les couleurs est aussi simple que :

<script type="text/javascript" src="/path/to/jquery.js"></script>
<script type="text/javascript">
    $('#CA').css('fill', 'blue');
    $('#NY').css('fill', '#ff0000');
</script>

1 votes

Merci pour ce tutoriel très précis et utile sur la façon de procéder. Je vais certainement utiliser votre solution comme sauvegarde, mais j'ai hâte d'essayer d'obtenir la compatibilité svg dans tous les principaux navigateurs.

1 votes

SVG n'est pas supporté dans ie8 ou inférieur sans exiger de l'utilisateur qu'il installe un plugin svg viewer - de la page SVG Wikipedia : "Tous les principaux navigateurs web modernes, supportent et rendent directement le balisage SVG à l'exception très notable de Microsoft Internet Explorer (IE)[3] La version bêta d'Internet Explorer 9 supporte l'ensemble des fonctionnalités SVG de base.[4] Actuellement, le support pour les navigateurs fonctionnant sous Android est également limité."

1 votes

Oui, mais svgweb semble aplanir toutes les incompatibilités en utilisant un peu de js et de flash. C'est la solution que j'ai choisie.

17voto

atomicjeep Points 393

Une autre option très rapide et précise est le navigateur sans tête phantomjs (webkit).

http://www.phantomjs.org/

14voto

psycho brm Points 2298

Lorsque vous convertissez un SVG en PNG transparent, n'oubliez pas de mettre ceci AVANT $imagick->readImageBlob() :

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

0 votes

Comment est-il possible d'appeler cette méthode avant de lire l'image, je reçois une erreur "Can not process empty Imagick object". Et oui mon extension imagick est installée car elle fonctionne et convertit les images.

0 votes

Vous êtes un homme bon, mon ami. Ce n'était pas une question, mais c'était nécessaire pour la réponse principale. Passez une bonne journée.

11voto

Spudley Points 85371

Vous mentionnez que vous faites cela parce que IE ne supporte pas le SVG.

La bonne nouvelle est qu'IE fait supportent les graphiques vectoriels. D'accord, c'est sous la forme d'un langage appelé VML que seul IE supporte, plutôt que SVG, mais il existe et vous pouvez l'utiliser.

Google Maps, entre autres, détectera les capacités du navigateur pour déterminer s'il doit servir SVG ou VML.

Ensuite, il y a le Bibliothèque de Raphael Il s'agit d'une bibliothèque graphique Javascript basée sur le navigateur, qui prend en charge SVG ou VML, en fonction du navigateur.

Un autre qui pourrait vous aider : SVGWeb .

Cela signifie que vous pouvez aider vos utilisateurs d'IE sans avoir à recourir à des graphiques bitmap.

Voir aussi la première réponse à cette question, par exemple : Transformation de SVG en VML par XSL

0 votes

+1 pour avoir mentionné raphael, qui est certainement une bonne solution et qui vaut la peine d'être étudiée pour son excellente implémentation des graphiques vectoriels multi-navigateurs.

7voto

C'est très facile, j'y travaille depuis quelques semaines.

Vous avez besoin de la Boîte à outils SVG Batik . Télécharger, et placez les fichiers dans le même répertoire que le SVG que vous voulez convertir en JPEG. Assurez-vous également de le 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

Cela devrait produire un JPEG du fichier SVG. C'est très facile. Vous pouvez même le placer dans une boucle et convertir des tas de 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')

0 votes

C'est génial. Merci pour le conseil. Je vais l'utiliser en conjonction avec perl pour traiter par lots des tas de fichiers SVG que j'ai créés à partir d'un modèle.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X