
我们去年就在emojiall.com这个网站中大量使用svg格式的矢量图,包括各emoji图片厂商和平台提供的svg矢量图以及我们自己的排行榜、情绪分析等原创生成的svg图,有一些svg是直接把svg代码放置在页面的html中,最近把一部分svg代码从页面html中拿出来单独作为独立文件,用img标签放在原来页面的html中,这样方便Google的收录,但百度等搜索引擎不能识别、解析和收录svg图片,于是我们也把svg图片转为png保存。
这个svg转png的功能以前就了解过一些,主要有两种方式:
- 使用PHP的Imagick插件
- 用JS将svg转为canvas绘制png
我们使用了第一种方式,下面是代码:
/**
* 函数:svg数据转png图片
* @param: svg数据
* @return: png图片
*/
function svg_data_to_png($input) {
$im = new Imagick();
$im->readImageBlob($input);
$im->setImageFormat("png8");
header("Content-type: image/png");
echo $im->getImageBlob();
$im->clear();
$im->destroy();
}下面是原始svg和转为png的对比:
svg图片:
png图片:

有一个坑:用上面的PHP方式转换后尺寸不合适,后来是通过修改原是svg图数据中的width和height来解决的。如果还有其它修改,也需要在转换png前进行修改。
另外,确实还有一些svg样式和特殊的语法在转换后的png中无法显示,也需要修改svg源码或者以后找其它办法解决。
2022年9月26日补充:上周自己编写了一个php程序,对apache日志进行统计,将耗时最长的一些访问列出,以发现性能瓶颈在什么地方,有针对性解决。该程序在www.emojiall.com网站所在的服务器上运行时,发现有一些svg转png的页面访问耗时长达几百秒,特别是生成1280x1280、1920x1920这种大尺寸png图片时更容易卡,今天进一步研究发现耗时几百秒的都是svg中带有所谓径向渐变标签的,例如:👎🏾 这个Emoji的Google SVG矢量图的源代码中包含:
<radialGradient id="e" cx="51.77" cy="27.401" r="87.039" gradientTransform="matrix(-.0021809 -1 -.7873 .001717 73.454 148.32)" gradientUnits="userSpaceOnUse"> <stop stop-color="#A56C43" offset=".6"/> <stop stop-color="#8D5738" offset="1"/> </radialGradient>
这其中的radialGradient就是径向渐变的标签,可以让svg的颜色变化更方便,但正是这个颜色渐变让Imagick的转换运算量大增,转为大尺寸的png图片需要几十甚至几百秒。使用正则表达式把cx / cy / r / gradientTransform / gradientUnits这些内容替换为空后,转换速度马上大幅提升,一秒内就可以转好。颜色信息不丢失,只是渐变效果丢失,还是可以接受的。👌
评论