2011-01-26 20 views
92

Sto lavorando a un progetto web che coinvolge una mappa degli Stati Uniti generata dinamicamente colorando stati diversi in base a una serie di dati.Converti immagine SVG in PNG con PHP

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

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

Qualsiasi soluzione che mi consenta di modificare dinamicamente i colori degli stati su una mappa degli Stati Uniti verrà presa in considerazione. La chiave è che è facile cambiare i colori al volo e che è cross browser. Solo soluzioni PHP/Apache, per favore.

+0

ci sono tutte le classi progettate per porto SVG verso VML? in questo modo potresti avere ancora una soluzione tipo "HTML5" – Patrick

+0

dai un'occhiata alla mia risposta. esattamente quello che ti serve –

risposta

115

Questo è divertente hai chiesto questo, ho appena fatto questo di recente per il sito del mio lavoro e pensavo che avrei dovuto scrivere un tutorial ... Ecco come si fa con ImageMagick: sostituzione del colore

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

la passi regex può variare a seconda del xml svg percorso e il modo in cui vengono memorizzati è id & valori di colore.Se non si desidera memorizzare un file sul server, è possibile uscita l'immagine come base 64 come

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

(prima di utilizzare chiaro/distruggere), ma per esempio ha problemi con PNG come Base64 in modo che ci probabilmente a base64 uscita come jpeg

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

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

Finitura: enter image description here

Modifica

Dopo aver scritto quanto sopra, mi è venuta in mente 2 tecniche migliorate:

1) invece di un ciclo regex per modificare il riempimento sullo stato , usare i CSS per fare le regole di stile come

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

e allora si può fare un unico testo sostituire a INIEZ t le tue regole css nella svg prima di procedere con la creazione di imagick jpeg/png. Se i colori non cambiano, verifica di non avere stili di riempimento in linea nei tag percorso che sostituiscono il css.

2) Se non è necessario creare effettivamente un file di immagine jpeg/png (e non è necessario supportare browser obsoleti), è possibile manipolare lo svg direttamente con jQuery. Non è possibile accedere ai percorsi SVG quando incorporanti la svg utilizzando img o oggetto tag, in modo da dovrete includere direttamente l'svg xml nella tua pagina web HTML come:

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

quindi cambiare i colori è 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> 
+1

Grazie per il tutorial molto preciso e utile su come farlo. Utilizzerò sicuramente la soluzione come backup, ma sono ansioso di provare a ottenere la compatibilità con svg su tutti i principali browser. –

+1

SVG non è supportato in ie8 o inferiore senza richiedere all'utente di installare un plug-in di svg viewer - dalla pagina di Wikipedia di SVG: "Tutti i principali browser Web moderni supportano e rendono il markup SVG direttamente con l'eccezione notevolissima di Microsoft Internet Explorer (IE) [3] La beta di Internet Explorer 9 supporta il set di funzioni SVG di base. [4] Attualmente, anche il supporto per i browser in esecuzione su Android è limitato. " – WebChemist

+1

Sì, ma svgweb sembra appianare tutte le incompatibilità usando un po 'di js e flash. Questa è la soluzione con cui sono andato. –

2

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 riga di comando o il binding PHP, IMagick, ma sembra avere un numero di stranezze e dipendenze esterne come mostrato, ad es. in this forum thread. Penso che sia ancora il modo più promettente per andare, è la prima cosa che vorrei esaminare se fossi in te.

+0

+1 Questa sarebbe la risposta semplice e migliore. –

11

Si dice che lo si sta facendo perché IE non supporta SVG.

La buona notizia è che IE fa grafica vettoriale di supporto. Va bene, quindi è nella forma di un linguaggio chiamato VML che supporta 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'è lo Raphael library, che è una libreria grafica basata su Javascript browswer, che supporta SVG o VML, sempre a seconda del browser.

Un'altra soluzione utile: SVGWeb.

Tutto ciò significa che è possibile supportare i propri utenti di IE senza dover ricorrere alla grafica bitmap.

Vedi anche la risposta in alto a questa domanda, per esempio: XSL Transform SVG to VML

+0

+1 per aver menzionato Raphael, che è sicuramente una buona soluzione e vale la pena investigare per la sua eccellente implementazione della grafica vettoriale cross-browser. – dmp

5

questo è v facile, sono state facendo il lavoro su questo per le ultime settimane.

È necessario il Batik SVG Toolkit. Scarica e posiziona i file nella stessa directory del file SVG che vuoi convertire in un JPEG, assicurati anche di decomprimerlo per primo.

Aprire il terminale, ed eseguire questo comando:

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. Si può anche solo collocarlo in un ciclo e convertire i 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') 
+0

Questo è fantastico. Grazie per il consiglio. Lo userò insieme a perl per elaborare in batch carichi di file SVG che ho creato da un modello. – simbabque

16

Un altro molto veloce & opzione è precisa la PhantomJS del browser senza testa (WebKit)

http://phantomjs.org/

+1

Dopo aver testato Batik, Imagemagick e alcune soluzioni basate sul web, phantomjs era l'unico modo per ottenere ciò che segue: ritaglio, mascheratura, effetti filtro, foreignObject (e anche il contenuto HTML che era stato posto di fronte a svg). Davvero posso raccomandare questo! –

3

si potrebbe usare canvg libreria js 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!

sto usando nel mio progetto ed effettivamente converte lo SVG in PNG (con l'aiuto di PHP per salvare il file ovviamente)

+1

collegamento interrotto :-( –

+1

Penso che questo violino faccia il lavoro http://jsfiddle.net/plaliberte/HAXyd/ e qui è la pagina di codice sorgente di canvg https://code.google.com/p/canvg/ – razor7

6

Durante la conversione in formato SVG in PNG trasparenti, non dimenticate di mettere questo prima di $ imagick-> readImageBlob():

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

è possibile utilizzare Raphaël—JavaScript Library e raggiungere facilmente. Funzionerà anche in IE.

+2

Aggiungi dettagli presenti nel link.Il link può rompersi in qualsiasi momento –

0
$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: Potrace demo: Tool4dev.com