在 Python 中将 SVG 转换为 PNG
如何在 Python 中将 svg
转换为 png
?我将 svg
存储在 StringIO
的实例中。我应该使用 pyCairo 库吗?我该如何编写该代码?
How do I convert an svg
to png
, in Python? I am storing the svg
in an instance of StringIO
. Should I use the pyCairo library? How do I write that code?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
这是我使用 cairosvg 所做的:
它就像一个魅力!
查看更多信息:cairosvg 文档
Here is what I did using cairosvg:
And it works like a charm!
See more: cairosvg document
答案是“pyrsvg” - librsvg。
Ubuntu python-rsvg 包提供了它。在 Google 中搜索它的名字很糟糕,因为它的源代码似乎包含在“gnome-python-desktop”Gnome 项目 GIT 存储库中。
我制作了一个极简主义的“hello world”,将 SVG 渲染到开罗
表面并将其写入磁盘:
更新:截至 2014 年,Fedora Linux 发行版所需的软件包是:
gnome-python2-rsvg
。上面的代码片段列表仍然按原样工作。The answer is "pyrsvg" - a Python binding for librsvg.
There is an Ubuntu python-rsvg package providing it. Searching Google for its name is poor because its source code seems to be contained inside the "gnome-python-desktop" Gnome project GIT repository.
I made a minimalist "hello world" that renders SVG to a cairo
surface and writes it to disk:
Update: as of 2014 the needed package for Fedora Linux distribution is:
gnome-python2-rsvg
. The above snippet listing still works as-is.安装 Inkscape 并将其作为命令行调用:
您还可以仅使用参数
-j
捕捉特定矩形区域,例如坐标“0:125:451:217”如果您只想显示一个对象在 SVG 文件中,您可以使用您在 SVG 中设置的对象 ID 来指定参数
-i
。它隐藏了其他一切。Install Inkscape and call it as command line:
You can also snap specific rectangular area only using parameter
-j
, e.g. co-ordinate "0:125:451:217"If you want to show only one object in the SVG file, you can specify the parameter
-i
with the object id that you have setup in the SVG. It hides everything else.我正在使用 Wand-py (围绕 ImageMagick 的 Wand 包装器的实现)导入一些相当高级的 SVG,到目前为止看到了很好的结果!这就是所需的全部代码:
我今天刚刚发现了这一点,并且觉得对于可能陷入这个答案的其他人来说值得分享,因为大多数问题得到解答已经有一段时间了。
注意:从技术上讲,在测试中我发现您实际上甚至不必传递 ImageMagick 的格式参数,因此
with wand.image.Image( blob=svg_file.read() ) 作为image:
就是真正需要的一切。编辑:根据 qris 的尝试编辑,这里有一些有用的代码,可让您将 ImageMagick 与具有透明背景的 SVG 一起使用:
I'm using Wand-py (an implementation of the Wand wrapper around ImageMagick) to import some pretty advanced SVGs and so far have seen great results! This is all the code it takes:
I just discovered this today, and felt like it was worth sharing for anyone else who might straggle across this answer as it's been a while since most of these questions were answered.
NOTE: Technically in testing I discovered you don't even actually have to pass in the format parameter for ImageMagick, so
with wand.image.Image( blob=svg_file.read() ) as image:
was all that was really needed.EDIT: From an attempted edit by qris, here's some helpful code that lets you use ImageMagick with an SVG that has a transparent background:
我没有发现任何令人满意的答案。所有提到的库都有一些问题或其他问题,比如 Cairo 放弃了对 python 3.6 的支持(他们在大约 3 年前放弃了对 Python 2 的支持!)。此外,在 Mac 上安装上述库也很痛苦。
最后,我发现最好的解决方案是svglib + reportlab。两者都使用 pip 顺利安装,并且第一次调用从 svg 转换为 png 效果非常好!对解决方案非常满意。
只需 2 个命令就可以解决问题:
我应该注意这些命令是否有任何限制?
I did not find any of the answers satisfactory. All the mentioned libraries have some problem or the other like Cairo dropping support for python 3.6 (they dropped Python 2 support some 3 years ago!). Also, installing the mentioned libraries on the Mac was a pain.
Finally, I found the best solution was svglib + reportlab. Both installed without a hitch using pip and first call to convert from svg to png worked beautifully! Very happy with the solution.
Just 2 commands do the trick:
Are there any limitations with these I should be aware of?
试试这个: http://cairosvg.org/
该网站说:
更新 2016 年 11 月 25 日:
Try this: http://cairosvg.org/
The site says:
Update November 25, 2016:
我刚刚在这里找到的另一个解决方案 如何渲染将 SVG 缩放为 QImage?
PySide 可以轻松地从 Windows 中的二进制包安装(我将它用于其他用途,所以对我来说很容易)。
然而,我在从维基媒体转换国家标志时注意到一些问题,所以可能不是最强大的 svg 解析器/渲染器。
Another solution I've just found here How to render a scaled SVG to a QImage?
PySide is easily installed from a binary package in Windows (and I use it for other things so is easy for me).
However, I noticed a few problems when converting country flags from Wikimedia, so perhaps not the most robust svg parser/renderer.
这是另一种不使用 rsvg 的解决方案(目前不适用于 Windows)。仅使用
pip install CairoSVG
svg2png.py安装 cairosvg
Here is a another solution without using rsvg(which is currently not available for windows).Only install cairosvg using
pip install CairoSVG
svg2png.py
对 jsbueno 的答案进行一点扩展:
A little extension on the answer of jsbueno:
这是一种由 Python 调用 Inkscape 的方法。
请注意,它会抑制 Inkscape 在正常无错误操作期间写入控制台的某些错误输出(特别是 stderr 和 stdout)。输出被捕获在两个字符串变量中:
out
和err
。例如,当在我的 Mac OS 系统上运行特定作业时,
out
最终为:(输入 svg 文件的大小为 339 x 339 像素。)
Here is an approach where Inkscape is called by Python.
Note that it suppresses certain crufty output that Inkscape writes to the console (specifically, stderr and stdout) during normal error-free operation. The output is captured in two string variables,
out
anderr
.For example, when running a particular job on my Mac OS system,
out
ended up being:(The input svg file had a size of 339 by 339 pixels.)
SVG 缩放和 PNG 渲染
使用 pycairo 和 librsvg 我能够实现 SVG 缩放并渲染为位图。假设您的 SVG 不完全是 256x256 像素(所需的输出),您可以使用 rsvg 将 SVG 读入 Cairo 上下文,然后对其进行缩放并写入 PNG。
main.py
RSVG C 绑定
来自 Cario 网站,稍作修改。也是如何从 Python 调用 C 库的一个很好的示例
SVG scaling and PNG rendering
Using pycairo and librsvg I was able to achieve SVG scaling and rendering to a bitmap. Assuming your SVG is not exactly 256x256 pixels, the desired output, you can read in the SVG to a Cairo context using rsvg and then scale it and write to a PNG.
main.py
RSVG C binding
From the Cario website with some minor modification. Also a good example of how to call a C-library from Python
尝试这个 python 脚本:
不要忘记安装 cairosvg:
pip3 install cairosvg
Try this python script:
Don't forget to install cairosvg:
pip3 install cairosvg
从这个 StackOverflow 答案发布我的代码。这是
svglib
+reportlib
不支持透明背景且不缩放的解决方法(请参阅@sarang 的回答 和 @ualter-jr 的回答回答以及关于缩放不起作用和这个关于透明度的)这使用
pyMuPDF
来渲染从reportlab
到 PNG 的中间 pdf。最大的优势是它不需要任何外部库,因为
pymupdf
附带了适用于Windows、Linux和MacOS的预编译轮子。整个事情就像
然后执行以下几行一样简单
Posting my code from this StackOverflow answer. It's a workaround to
svglib
+reportlib
not supporting a transparent background and no scaling (see @sarang's answer and @ualter-jr's answer as well as these Github issues on scaling not working and this one on transparency)This uses
pyMuPDF
to render an intermediate pdf fromreportlab
to PNG.The big advantage is that it doesn't need any external libraries as
pymupdf
comes with precompiled wheels for Windows, Linux and MacOS.The whole thing is as easy as
and then executing the following lines
尝试使用 Gtk.Image 和 Gdk.Pixbuf
Try using Gtk.Image and Gdk.Pixbuf
实际上,除了 Python(Cairo、Ink 等)之外,我不想依赖任何其他东西
我的要求是尽可能简单,最多一个简单的
pip install "savior"
就足够了,这就是为什么上述任何一个都不适合我。我经历了这个(比 Stackoverflow 的研究更进一步)。
https:// /www.tutorialexample.com/best-practice-to-python-convert-svg-to-png-with-svglib-python-tutorial/
到目前为止看起来不错。所以我分享一下,以防有人遇到同样的情况。
Actually, I did not want to be dependent of anything else but Python (Cairo, Ink.., etc.)
My requirements were to be as simple as possible, at most, a simple
pip install "savior"
would suffice, that's why any of those above didn't suit for me.I came through this (going further than Stackoverflow on the research).
https://www.tutorialexample.com/best-practice-to-python-convert-svg-to-png-with-svglib-python-tutorial/
Looks good, so far. So I share it in case anyone in the same situation.
这里的所有答案都很好,但我想我会提到我已经制作了一个简单的库,它将 SVG 文件加载为枕头图像实例,然后可以将其导出。它像 blj 的答案一样使用 inkscape,但渲染到标准输出,以便不创建临时文件。 README 中有一些基本的使用内容。
https://github.com/jlwoolf/pillow-svg
编辑:
正如所建议的,这里有一个简短的解释,因为链接可能会变得无效:
该库使用 inkscape 的命令行界面,使用 python 子进程库将图像转换为特定大小或 dpi 的 png。通过将
--export-filename
设置为-
,inkscape 将输出重定向到 stdout。前两行被丢弃,剩余的输出被传递到 PIL.Image.open ,将其转换为枕头图像实例。从那里您可以执行所需的任何枕头图像操作(例如导出为 jpg、调整大小、裁剪等)。
编辑2:
刚刚添加了对 skia-python 的支持(尚未完全测试,但似乎有效迄今为止)。这样,您只需安装一次 pip 即可将 svg 转换为 png(无需使用 inkscape)。
以下是该库如何使用skia-python 的说明:
首先,将 svg 文件加载到
skia.SVGDOM
中。从那里您可以使用containerSize
获取 SVGDOM 的尺寸。然后制作所需图像输出尺寸的skia.Surface
。缩放画布以使 svg 适合表面,然后渲染 svg。从那里,可以制作图像快照,然后将其馈送到PIL.Image.open
。编辑3:
我使图书馆变得更加充实。现在有一个命令行实用程序可以轻松进行 svg 转换,还有更多解释用法的文档。希望有帮助!
All the answer's here are great, but I figure I'll mention that I have made a simple library that loads SVG's files as pillow Image instances which can then be exported. It uses inkscape like in blj's answer, but renders to stdout so that no temporary files are made. There's some basic usage stuff in the README.
https://github.com/jlwoolf/pillow-svg
EDIT:
As suggested, here's a brief explanation, since the link could become invalid:
The library uses inkscape's command line interface to convert the image to a png of a specific size or dpi using the python subprocess library. By setting
--export-filename
to-
, inkscape redirects the output to the stdout. The first two lines are discarded, and the remaining output is passed toPIL.Image.open
, converting it to pillow image instance.From there you can do whatever pillow image operations you need (like export as a jpg, resize, crop, etc).
EDIT 2:
Just added support for skia-python (haven't fully tested it, but seems to work so far). This way you can convert an svg to png with only a single pip install (no need to use inkscape).
Here is an explanation of how the library uses skia-python:
First, the svg file is loaded into a
skia.SVGDOM
. From there you can grab the SVGDOM's dimensions, usingcontainerSize
. Then askia.Surface
of the desired image output size is made. The canvas is scaled to fit the svg to the surface, and then the svg is rendered. From there, an image snapshot can be made, which can then be fed toPIL.Image.open
.Edit 3:
I have fleshed out the library much much more. There is a command line utility now for easy svg conversion, along with more documentation explaining usage. Hope it helps!