如何在 Python 中将 SVG 图像渲染为 PNG 文件?

Posted

技术标签:

【中文标题】如何在 Python 中将 SVG 图像渲染为 PNG 文件?【英文标题】:How to render SVG image to PNG file in Python? 【发布时间】:2021-12-08 02:43:48 【问题描述】:

所以我想从具有目标分辨率 WxH 的 python 代码渲染 SVG(将 SVG 文本作为 str,like this 我动态生成):

<svg   viewBox="0 0 220 220"
     xmlns="http://www.w3.org/2000/svg">
  <filter id="displacementFilter">
    <feTurbulence type="turbulence" baseFrequency="0.05"
        numOctaves="2" result="turbulence"/>
    <feDisplacementMap in2="turbulence" in="SourceGraphic"
        scale="50" xChannelSelector="R" yChannelSelector="G"/>
  </filter>

  <circle cx="100" cy="100" r="100"
      style="filter: url(#displacementFilter)"/>
</svg>

转换成 png 图像。如何在 Python 中做这样的事情?

【问题讨论】:

这能回答你的问题吗? Convert SVG to PNG in Python 【参考方案1】:

有多种解决方案可用于在 python 中将 svgs 转换为 pngs,但由于您使用的是 svg 过滤器,因此并非所有解决方案都适用于您的特定用例。

solution filter works? alpha channel? call directly from python?
cairosvg some* yes yes
svglib no no yes
inkscape yes yes via subprocess
wand yes yes yes

*来自cairosvg documentation:

仅支持 feOffsetfeBlendfeFlood 过滤器。


注意:我为所有示例图像添加了纯白色背景,以便在深色背景上更容易看到,除非上表中另有说明,否则原件确实具有透明背景


cairosvg

import cairosvg

# read svg file -> write png file
cairosvg.svg2png(url=input_svg_path, write_to=output_png_path, output_width=width, output_height=height)

# read svg file -> png data
png_data = cairosvg.svg2png(url=input_svg_path, output_width=width, output_height=height)

# svg string -> write png file
cairosvg.svg2png(bytestring=svg_str.encode(), write_to=output_png_path, output_width=width, output_height=height)

# svg string -> png data
png_data = cairosvg.svg2png(bytestring=svg_str.encode(), output_width=width, output_height=height)

svglib

from svglib.svglib import svg2rlg
from reportlab.graphics import renderPM

# read svg -> write png
renderPM.drawToFile(svg2rlg(input_svg_path), output_png_path, fmt='PNG')

inkscape

要读取文件作为输入,请将文件的路径作为最后一个参数。 要使用字符串作为输入,请添加 --pipe 参数并将字符串传递给标准输入。

要写入文件作为输出,请将参数--export-filename=+path 添加到输出文件。 要直接获取输出内容而不写入文件,请使用--export-filename=-,它将被发送到标准输出。

CLI 选项的完整文档here

import subprocess
inkscape = ... # path to inkscape executable

# read svg file -> write png file
subprocess.run([inkscape, '--export-type=png', f'--export-filename=output_png_path', f'--export-width=width', f'--export-height=height', input_svg_path])

# read svg file -> png data
result = subprocess.run([inkscape, '--export-type=png', '--export-filename=-', f'--export-width=width', f'--export-height=height', input_svg_path], capture_output=True)
#   (result.stdout will have the png data)

# svg string -> write png file
subprocess.run([inkscape, '--export-type=png', f'--export-filename=output_png_path', f'--export-width=width', f'--export-height=height', '--pipe'], input=svg_str.encode())

# svg string -> png data
result = subprocess.run([inkscape, '--export-type=png', '--export-filename=-', f'--export-width=width', f'--export-height=height', '--pipe'], input=svg_str.encode(), capture_output=True)
#   (result.stdout will have the png data)

wand

from wand.image import Image
from wand.Color import Color

with Color('#00000000') as bgcolor,\
  # to read input from a file:
  Image(filename=input_svg_path, width=width, height=height, background=bgcolor) as img:
  # or, to use input from a string:
  Image(blob=svg_str.encode(), format='svg', width=width, height=height, background=bgcolor) as img:
    # to save output to a file:
    with img.convert('png') as output_img:
        output_img.save(filename=output_png_path)
    # or, to get the output data in a variable:
    png_data = img.make_blob(format='png')

【讨论】:

【参考方案2】:

你可以使用CairoSVG

CairoSVG 在 PyPI 上可用,您可以使用 pip 安装它:

pip3 install cairosvg

在您的代码中:

import cairosvg

width = 640
height = 480
cairosvg.svg2png(url='logo.svg', write_to='image.png', output_width=width, output_height=height)

【讨论】:

以上是关于如何在 Python 中将 SVG 图像渲染为 PNG 文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用Javascript将FontAwesome渲染为SVG图像?

在节点中将 svg 图像从 url 转换为 base64

在节点中将 svg 图像从 url 转换为 base64

在浏览器中将 SVG 转换为图像(JPEG、PNG 等)

在使用canvas api在浏览器中将svg转换为png时,svg中的嵌入图像在Safari中随机空白

如何在python中使用修改后的输出大小绘制混淆矩阵并输出为.svg图像?