Converti l'image SVG in PNG con PHP

Sto lavorando a un progetto web che coinvolge una mappa degli Stati Uniti generata dynamicmente colorando stati diversi in base a una serie di dati.

Questo file SVG mi offre una buona mappa vuota degli Stati Uniti ed è molto facile cambiare il colore di each stato. La difficoltà è che i browser IE non supportno SVG quindi, per poter utilizzare la syntax pratica delle offerte svg, dovrò convertirlo in JPG.

Idealmente, mi piacerebbe farlo solo con la libreria GD2 ma potrei anche usare ImageMagick. Non ho assolutamente idea di come farlo.

Sarà presa in considerazione qualsiasi soluzione che mi permetta di cambiare dynamicmente i colors degli stati su una mappa degli Stati Uniti. La chiave è che è facile cambiare i colors al volo e che è cross browser. Solo soluzioni PHP / Apache, per favore.

È buffo che tu abbia chiesto questo, l'ho appena fatto di recente per il sito del mio lavoro e stavo pensando che dovrei scrivere un tutorial … Ecco come farlo con 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 = arrays( "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(); 

i passaggi che regex la sostituzione del colore possono variare in base al path xml svg e al modo in cui vengono memorizzati i valori id e i valori dei colors. Se non si desidera memorizzare un file sul server, è ansible printingre l'image come base 64

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

(prima di usare clear / destroy) ma, ad esempio, ha problemi con PNG come base64, quindi probabilmente dovresti generare base64 come jpeg

puoi vedere un esempio qui che ho fatto per la mappa del territorio di vendita di un ex datore di lavoro:

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

Finire: inserisci la descrizione dell'immagine qui

modificare

Da quando ho scritto quanto sopra, ho messo a punto 2 tecniche migliorate:

1) invece di un ciclo regex per modificare lo stato di riempimento, usa il CSS per fare le regole di stile

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

e quindi puoi fare un solo text sostitutivo per iniettare le tue regole css nella svg prima di procedere con la creazione di imagick jpeg / png. Se i colors non cambiano, verifica di non avere stili di riempimento in linea nei tag path che sostituiscono il css.

2) Se non è necessario creare effettivamente un file image jpeg / png (e non è necessario supportre browser obsoleti), è ansible manipolare lo svg direttamente con jQuery. Non è ansible accedere ai routes svg quando si incorpora lo svg usando i tag img o object, quindi sarà necessario includere direttamente la xml svg nella pagina Web come html:

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

quindi cambiare i colors è facile come:

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

Un'altra opzione molto veloce e precisa è il browser senza testa PhantomJS (webkit)

http://phantomjs.org/

Si dice che lo stai facendo perché IE non support SVG.

La buona notizia è che IE support la grafica vettoriale. Va bene, quindi è nella forma di un linguaggio chiamato VML che support solo IE, piuttosto che SVG, ma è lì, e puoi usarlo.

Google Maps, tra gli altri, rileverà le funzionalità del browser per determinare se servire SVG o VML.

Poi c'è la libreria Raphael , che è una libreria grafica basata su Javascript browswer, che support SVG o VML, sempre a seconda del browser.

Un altro che può aiutare: SVGWeb .

Tutto ciò significa che puoi supportre i tuoi utenti di IE senza wherer ricorrere alla grafica bitmap.

Vedi anche la risposta più alta a questa domanda, ad esempio: XSL Transform SVG to VML

Quando si converte SVG in PNG trasparente, non dimenticare di inserire PRIMA $ imagick-> readImageBlob ():

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

Questo è molto facile, ci siamo impegnati su questo nelle ultime settimane.

Hai bisogno del Batik SVG Toolkit . Scarica e posiziona i file nella stessa directory dell'SVG che vuoi convertire in JPEG , assicurati anche di decomprimerlo per primo.

Apri il terminal ed esegui questo command:

 java -jar batik-rasterizer.jar -m image/jpeg -q 0.8 NAME_OF_SVG_FILE.svg 

Questo dovrebbe produrre un JPEG del file SVG. Davvero facile. Puoi persino metterlo in un loop e convertire carichi di 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') 

puoi usare canvg js library per convertire l'SVG in PNG, maggiori informazioni qui http://paksula.users.cs.helsinki.fi/svg_open_2010/demo.xhtml compatibile con tutti i principali browser!

Lo sto usando nel mio progetto e in realtà converte l'SVG in PNG (con l'aiuto di PHP per salvare il file ovviamente)

Non conosco una soluzione autonoma di PHP / Apache, in quanto ciò richiederebbe una libreria PHP in grado di leggere e visualizzare immagini SVG. Non sono sicuro che esista una tale biblioteca – non ne conosco nessuno.

ImageMagick è in grado di rasterizzare i file SVG, tramite la row di command o il binding PHP, IMagick , ma sembra avere un numero di stranezze e dependencies esterne, come mostrato in questo thread del forum . Penso che sia ancora il modo più promettente per andare, è la prima cosa che vorrei esaminare se fossi in te.

 $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); 

o utilizzando: demo di potrace : Tool4dev.com

Puoi usare Raphaël-JavaScript Library e realizzarlo facilmente. Funzionerà anche in IE.