Convert SVG image to PNG with PHP

后端 未结 8 2080
没有蜡笔的小新
没有蜡笔的小新 2020-11-22 14:46

I\'m working on a web project that involves a dynamically generated map of the US coloring different states based on a set of data.

This SVG file gives me a good b

8条回答
  •  情歌与酒
    2020-11-22 15:32

    That's funny you asked this, I just did this recently for my work's site and I was thinking I should write a tutorial... Here is how to do it with PHP/Imagick, which uses 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();
    

    the steps regex color replacement may vary depending on the svg path xml and how you id & color values are stored. If you don't want to store a file on the server, you can output the image as base 64 like

    ';?>
    

    (before you use clear/destroy) but ie has issues with PNG as base64 so you'd probably have to output base64 as jpeg

    you can see an example here I did for a former employer's sales territory map:

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

    Finish: enter image description here

    Edit

    Since writing the above, I've come up with 2 improved techniques:

    1) instead of a regex loop to change the fill on state , use CSS to make style rules like

    
    

    and then you can do a single text replace to inject your css rules into the svg before proceeding with the imagick jpeg/png creation. If the colors don't change, check to make sure you don't have any inline fill styles in your path tags overriding the css.

    2) If you don't have to actually create a jpeg/png image file (and don't need to support outdated browsers), you can manipulate the svg directly with jQuery. You can't access the svg paths when embedding the svg using img or object tags, so you'll have to directly include the svg xml in your webpage html like:

    then changing the colors is as easy as:

    
    
    

提交回复
热议问题