如何用ImageMagick将SVG转换为PNG ?

我有一个定义为16x16大小的SVG文件。当我使用ImageMagick的转换程序将其转换为PNG时,我得到了一个16x16像素的PNG,太小了:

convert test.svg test.png

我需要指定输出PNG的像素大小。-size参数似乎被忽略了,-scale参数缩放PNG 它已经转换为PNG。到目前为止,我使用-density参数得到的最好结果是:

convert -density 1200 test.svg test.png

但我并不满意,因为我想指定以像素为单位的输出大小,而不做数学运算来计算密度值。所以我想这样做:

convert -setTheOutputSizeOfThePng 1024x1024 test.svg test.png

这里我要用到的神奇参数是什么?

299200 次浏览

这不是完美的,但它做到了。

convert -density 1200 -resize 200x200 source.svg target.png

基本上,它增加了足够高的DPI(只是使用一个有根据的/安全的猜测),调整大小是有足够质量的。我试图找到一个合适的解决方案,但过了一段时间后,我认为这已经足够满足我目前的需求了。

注意:使用200x200!强制执行给定的决议

为什么不试试inkscape命令行,这是我的bat文件,将所有SVG在这个目录转换为png:

●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●●

在这个例子中,我还没有能够从ImageMagick得到很好的结果,但Inkscape在Linux和Windows上缩放SVG方面做得很好:

# Inkscape v1.0+
inkscape -w 1024 -h 1024 input.svg -o output.png
# Inkscape older than v1.0
inkscape -z -w 1024 -h 1024 input.svg -e output.png

注意,您可以省略一个宽度/高度参数,让另一个参数根据输入图像尺寸自动缩放。

下面是使用这个命令将16x16的SVG缩放为200x200的PNG的结果:

enter image description here

enter image description here

为了重新缩放图像,应该使用-density选项。据我所知,标准密度是72,对应尺寸为1:1。如果你想要输出png是原始svg的两倍大,将密度设置为72*2=144:

convert -density 144 source.svg target.png

尝试# EYZ0:

svgexport input.svg output.png 64x
svgexport input.svg output.png 1024:1024

svgexport是一个简单的跨平台命令行工具,我已经为导出svg文件到jpg和png,参见在这里更多的选项。安装svgexport 安装npm,然后运行:

npm install svgexport -g

编辑:如果您发现库的问题,请在GitHub上提交,谢谢!

如果你在MacOS X上,Imagemagick的转换有问题,你可以尝试用RSVG库重新安装它。 使用自制程序:< / p >
brew remove imagemagick
brew install imagemagick --with-librsvg

验证它是否正确地委托:

$ convert -version
Version: ImageMagick 6.8.9-8 Q16 x86_64 2014-12-17 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2014 ImageMagick Studio LLC
Features: DPC Modules
Delegates: bzlib cairo fontconfig freetype jng jpeg lcms ltdl lzma png rsvg tiff xml zlib

它应该显示rsvg

我来到这个帖子-但我只是想做批量和快速的转换,而不使用任何参数(由于几个文件大小不同)。

rsvg drawing.svg drawing.png

对我来说,这些要求可能比原作者要简单一些。(想在MS PowerPoint中使用SVGs,但它不允许)

当svg单位不是px(例如cm)时,Inkscape似乎无法工作。我得到一个空白图像。也许,它可以通过旋转dpi来修复,但它太麻烦了。

Svgexport是一个node.js程序,所以通常不太有用。

Imagemagick的转换工作正常:

 convert -background none -size 1024x1024 infile.svg outfile.png

如果您使用-resize,图像是模糊的,文件要大得多。

最好的

rsvg-convert -w 1024 -h 1024 infile.svg -o outfile.png

它速度最快,依赖性最小,输出比convert小30%左右。安装librsvg2-bin获取:

sudo apt install -y librsvg2-bin

似乎没有手册页,但你可以输入:

rsvg-convert --help

去寻求帮助。简单就是好。

我通过更改<svg>标签的widthheight属性来匹配我预期的输出大小,然后使用ImageMagick进行转换,从而解决了这个问题。效果非常好。

下面是我的Python代码,一个将返回JPG文件内容的函数:

import gzip, re, os
from ynlib.files import ReadFromFile, WriteToFile
from ynlib.system import Execute
from xml.dom.minidom import parse, parseString




def SVGToJPGInMemory(svgPath, newWidth, backgroundColor):


tempPath = os.path.join(self.rootFolder, 'data')
fileNameRoot = 'temp_' + str(image.getID())


if svgPath.lower().endswith('svgz'):
svg = gzip.open(svgPath, 'rb').read()
else:
svg = ReadFromFile(svgPath)


xmldoc = parseString(svg)


width = float(xmldoc.getElementsByTagName("svg")[0].attributes['width'].value.split('px')[0])
height = float(xmldoc.getElementsByTagName("svg")[0].attributes['height'].value.split('px')[0])


newHeight = int(newWidth / width * height)


xmldoc.getElementsByTagName("svg")[0].attributes['width'].value = '%spx' % newWidth
xmldoc.getElementsByTagName("svg")[0].attributes['height'].value = '%spx' % newHeight


WriteToFile(os.path.join(tempPath, fileNameRoot + '.svg'), xmldoc.toxml())
Execute('convert -background "%s" %s %s' % (backgroundColor, os.path.join(tempPath, fileNameRoot + '.svg'), os.path.join(tempPath, fileNameRoot + '.jpg')))


jpg = open(os.path.join(tempPath, fileNameRoot + '.jpg'), 'rb').read()


os.remove(os.path.join(tempPath, fileNameRoot + '.jpg'))
os.remove(os.path.join(tempPath, fileNameRoot + '.svg'))


return jpg
@808sound上面的答案对我没用。我想调整一下尺寸 # EYZ0 < / p > < p > # EYZ0 < / p >

所以我打开Inkscape,然后转到File, # eyz1,弹出一个GUI框,允许我设置我需要的精确尺寸。

Ubuntu 16.04 Linux上的版本: # EYZ0 < / p >

(顺便说一下,这张图片来自肯尼。Nl的资产包)

在遵循何塞·阿尔班的回答是中的步骤之后,我能够使用以下命令让ImageMagick工作得很好:

convert -density 1536 -background none -resize 100x100 input.svg output-100.png

数字1536来自密度的大概估计,参见这个答案了解更多信息。

让我头疼的一件事是在输入文件名之后设置-density。这并没有起作用。移动到转换的第一个选项(在其他任何东西之前)使它工作(对我来说,YMMV等)。

对于简单的SVG到PNG转换,我发现cairosvg (https://cairosvg.org/)比ImageMagick执行得更好。安装和运行目录中所有SVG文件的步骤。

pip3 install cairosvg

在包含.svg文件的目录中打开一个python shell,然后运行:

import os
import cairosvg


for file in os.listdir('.'):
name = file.split('.svg')[0]
cairosvg.svg2png(url=name+'.svg',write_to=name+'.png')

这也将确保您不会覆盖原始的.svg文件,但将保持相同的名称。然后你可以移动你所有的。png文件到另一个目录:

$ mv *.png [new directory]

如果没有librsvg,你可能会得到一个黑色的png/jpeg图像。我们必须用imagemagick安装librsvgconvert svg文件。

Ubuntu

 sudo apt-get install imagemagick librsvg
convert -density 1200 test.svg test.png


MacOS

 brew install imagemagick librsvg
convert -density 1200 test.svg test.png


在ImageMagick中,如果使用Inkscape或RSVG与ImageMagick一起渲染,就会得到更好的SVG渲染,而不是自己内部的MSVG/XML渲染。RSVG是一个委托,需要与ImageMagick一起安装。如果Inkscape安装在系统上,ImageMagick将自动使用它。我使用Inkscape在ImageMagick下面。

没有什么“神奇的”参数可以满足您的需求。

但是,我们可以非常简单地计算出渲染输出所需的精确密度。

下面是一个小的50x50按钮,默认渲染密度为96:

convert button.svg button1.png
< p > < br > # EYZ0 < / p >

假设我们希望输出是500。输入是50,默认密度为96(旧版本的Inkscape可能使用92)。所以你可以根据尺寸和密度的比例来计算所需的密度。

512/50 = X/96
X = 96*512/50 = 983

< br >

convert -density 983 button.svg button2.png
< p > < br > # EYZ0 < / p >

在ImageMagick 7中,您可以按照如下方式进行计算:

magick -density "%[fx:96*512/50]" button.svg button3.png


or


in_size=50
in_density=96
out_size=512


magick -density "%[fx:$in_density*$out_size/$in_size]" button.svg button3.png

在使用brew的macOS上,直接使用librsvg效果很好

brew install librsvg
rsvg-convert test.svg -o test.png

通过rsvg-convert --help可以获得许多选项

在Linux上用Inkscape 1.0将svg转换为png需要使用

inkscape -w 1024 -h 1024 input.svg --export-file output.png

inkscape -w 1024 -h 1024 input.svg --export-filename output.png

这对我来说是最有效的,也是最容易运行的。

find . -type f -name "*.svg" -exec bash -c 'rsvg-convert -h 1000  $0 > $0.png' {} \;
rename 's/svg\.png/png/' *

这将循环当前文件夹和子文件夹中的所有文件,寻找.svg文件,并将其转换为透明背景的png。

确保已经安装了librsvg并重命名了util

brew install librsvg
brew install rename

透明背景,使用ImageMagick 7以目标高度/大小导出:

magick -background none -size x1080 in.svg out.png

单线质量变换器:

for i in *svg; do magick -background none -size x1080 "$i" "${i%svg}png"; done

我得到了“低聚”;曲线采用增加密度的一般方法。所以我决定深入挖掘并解决这个问题,因为这似乎是这种方法的一个副作用,我认为这与原始密度或dpi有关。

在这个回答回答中,我们已经看到72和96被建议作为图像的默认密度,但哪一个呢?如果我的不一样呢?

ImageMagick有一种方法来整理:

identify -verbose test.svg

这将输出大量关于图像文件的元数据,包括:

Image:
Filename: test.svg
Format: SVG (Scalable Vector Graphics)
Mime type: image/svg+xml
Class: ...
Geometry: ...
Resolution: 37.79x37.79
Print size: ...
Units: PixelsPerCentimeter
# and a whole lot MORE ...

对于更简洁的查询,您可以尝试:

identify -format "%x x %y %U" test.svg
=> 37.789999999999999147 x 37.789999999999999147 PixelsPerCentimeter

根据这个论坛帖子的建议,并使用文档进行修改

现在我们知道了图像的当前密度,但可能需要将其转换为正确的转换或mogriing单位(PixelsPerInch或dpi)

这是一个简单的pixelspercm x 2.54的计算

37.789999999999999147 x 2.54 = 95.9866 ~> 96

如果你更喜欢图表或在线计算器,你可以尝试https://www.pixelto.net/cm-to-px-converter

现在,我们已经将正确的原始密度转换为dpi,上述答案中所述的其余逻辑就都到位了,SVG文件可以缩放到更好的“分辨率”。乘以原始密度。

原始的密度对于我来说太像素化了,所以在我的情况下,5倍原始密度或-density 480对我来说已经足够了。记住,这也会调整图像的大小,与原始的svg相比,当使用/实现图像时,您将需要为此进行调整。

注意:我也尝试了Inkscape方法,也有像素问题,但已经看到了密度方法的改进,所以我决定更深入地挖掘它。然而,Inkscape尝试的输出给了我一个想法,你也可以用它来确定dpi,但是为了得到你已经可以用ImageMagick得到的东西,需要安装很多东西

Area 0:0:20.75:17 exported to 21 x 17 pixels (96 dpi)