【问题标题】:How to convert a SVG to a PNG with ImageMagick?如何使用 ImageMagick 将 SVG 转换为 PNG?
【发布时间】:2012-04-08 20:19:25
【问题描述】:

我有一个定义为 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

那么我必须在这里使用的魔法参数是什么?

【问题讨论】:

  • 例如-size 1024x1024 工作正常,你的 imagemagick 版本是多少?
  • ImageMagick-6.9.0-Q16。 convert -resize 1024x1024 foo.svg foo.png 工作正常。
  • @Jichao -resize 只是拉伸转换后的图像,结果质量很差。
  • convert -size 1024x1024 test.svg test.png 适用于 ImageMagick 7.0.7-0 Q16(Windows 的 Chocolatey 存储库中的当前版本)。只需确保 -size 出现在输入文件名之前,否则 16x16 的图片将被放大以产生模糊的结果。

标签: svg imagemagick png


【解决方案1】:

在这种情况下,我无法从 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 的结果:

【讨论】:

  • +1 就 imagemagick 而言。 SVG 引擎似乎有问题。在大多数情况下,我无法使用它获得准确的结果。 Inkscape,OTOH,工作得非常好。
  • 我认为 Inkscape 是继 Linux 之后最令人印象深刻的 OSS 示例。感谢您的提示!
  • 在 OSX 上也能很好地工作。
  • 在 OSX 上,为 X11 安装了 Inkscape,它对我有用:/Applications/Inkscape.app/Contents/Resources/bin/inkscape -z -e test.png -w 1024 -h 1024 test.svg
  • @Rörd 要使用 ImageMagick 保持背景透明,请使用 -background none 命令行选项。
【解决方案2】:

试试svgexport:

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

svgexport 是一个简单的跨平台命令行工具,用于将 svg 文件导出为 jpg 和 png,请参阅here 了解更多选项。要安装 svgexport install npm,然后运行:

npm install svgexport -g

编辑:如果您发现库有问题,请在 GitHub 上submit it,谢谢!

【讨论】:

  • svgexport 对我来说非常有用。输出匹配浏览器渲染比 ImageMagick 更接近。
  • 这对我也很有效。与在 GUI 工具中手动执行相比,实时节省。无论如何,很难在 Mac 上找到一个能够很好地处理 SVG 且价格便宜的 GUI 应用程序
  • svgexport 在 OSX 上没有为我做任何事情,只是以空白图像结束
  • 效果很好,但会产生巨大的图像。使用 optipng,我能够将我的文本徽标从 3 MB 压缩到 ~20kB。
  • evgexport 根据大小创建巨大的 png 文件。推荐 svg2png,它也使用 PhantomJS 进行导出,但创建的图像要小得多。
【解决方案3】:

这并不完美,但确实可以。

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

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

注意:使用 200x200!强制给定分辨率

【讨论】:

  • 在我的情况下不透明度和阴影丢失了。
  • 我没有复杂的 svg,所以这对我有用。 -resize 200% 不起作用,我必须以像素为单位指定大小。
  • @jiyinyiyong 要使用 ImageMagick 保持背景透明,请使用 -background none 命令行选项。为了保持图像比例,您也可以只指定一个维度,如宽度为 -resize 200 或高度为 -resize x200。请参阅:imagemagick.org/script/command-line-processing.php#geometry 了解详尽的 ImageMagick 几何形状 选项。
  • 对我也不起作用。结果全是模糊的。
  • (这适用于linux,可能适用于windows)如果你在IM上打开-verbose,那么看起来IM本身使用inkscape来创建一个中间eps文件。因此我建议按照@808sound 的建议直接使用inkscape
【解决方案4】:

如果您在 MacOS X 上并且在使用 Imagemagick 的转换时遇到问题,您可以尝试使用 RSVG 库重新安装它。 使用 HomeBrew:

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

【讨论】:

  • 对我来说效果很好 - 默认的 convert 确实将 svg 转换为 png,但结果毫无希望;重新安装后,它们是完美的。此外,转换速度明显更快。
  • 这在 Mac OSX 上对我有用。我没有发现新的转换更快,但更准确。我强烈建议所有 Mac OSX 用户尝试一下。
  • 这应该是公认的答案,哦,好吧。谢谢你,工作就像一个魅力,否则我永远不会知道采取这些步骤
  • 在莫哈韦沙漠我得到invalid option: --with-librsvg
  • @zaitsman 可能为时已晚,但是...参数选项已更改,请尝试使用--with-rsvg。而且我认为它需要安装librsvg2-bin 包。见gist.github.com/maxivak/1476f7e979879da9f75371a86d5627b5
【解决方案5】:

当 svg 单位不是 px(例如厘米)时,Inkscape 似乎不起作用。我得到一个空白图像。或许,可以通过调一下dpi来解决,但是太麻烦了。

Svgexport 是一个 node.js 程序,因此通常没有用处。

Imagemagick 的转换适用于:

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

如果使用-resize,图片模糊,文件大很多。

最佳

~$ rsvg  -w 1024 -h 1024 infile.svg  outfile.png

它最快,依赖最少,输出比convert小30%左右。安装 librsvg2-bin 以获取它。似乎没有手册页,但您可以键入:

~$ rsvg --help

寻求帮助。简单就好。

【讨论】:

  • 这很容易是最好的答案(我不知道为什么二十个不同的答案会给出相同的 imagemagick 响应);它保留了颜色和阴影,并且不会破坏任何东西。但是,为了匹配 imagemagick 调整大小的行为(特别是,WxH 表示缩放图像以适合该大小的框,保持纵横比),-a 参数应与 rsvg 一起使用。
  • 这破坏了我的图像,各种奇怪的文物。 inkscape 做得更好。
  • 请注意,brew install rsvg 在 OSX 上安装了一百万个东西 - GDK、OpenSSL、Python 等。
  • 仅供参考,当前安装命令为brew install librsvg,转换命令为rsvg-convert
  • 我发现 librsvg(如果是 Arch,则为 rsvg-convert)在将复杂的 svg 转换为 png 时可以提供最佳和最一致的结果。跟进optipng 以减少输出文件大小。
【解决方案6】:

按照Jose Alban's answer 中的步骤操作后,我可以使用以下命令让 ImageMagick 正常工作:

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

数字 1536 来自对密度的粗略估计,请参阅this answer 了解更多信息。

【讨论】:

    【解决方案7】:

    为了重新缩放图像,应使用选项-density。据我所知,标准密度是 72 并且映射大小为 1:1。如果希望输出的 png 是原始 svg 的两倍大,请将密度设置为 72*2=144:

    convert -density 144 source.svg target.png
    

    【讨论】:

    • 请注意,转换选项必须在输入文件之前。 IE。 convert source.svg -density 144 target.png 不会重新缩放图像。
    • 其实标准密度好像是90,所以应该是convert -density 180 source.svg target.png
    【解决方案8】:

    在 ImageMagick 中,如果将 Inkscape 或 RSVG 与 ImageMagick 一起使用,则可以获得比其自己的内部 MSVG/XML 渲染更好的 SVG 渲染。 RSVG 是一个需要与 ImageMagick 一起安装的委托。如果系统上安装了 Inkscape,ImageMagick 将自动使用它。我在下面的 ImageMagick 中使用 Inkscape。

    没有“魔法”参数可以满足您的需求。

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

    这是一个 50x50 的小按钮,默认密度为 96:

    convert button.svg button1.png
    


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

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


    convert -density 983 button.svg button2.png
    


    在 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
    

    【讨论】:

    • +1 用于避免单独命令或使用计算器的神奇 fx 表达式。附带说明一下,如果您运行 identify -format "%x x %y (%w x %h) file.svg,您还将获得输出中默认密度的宽度和高度(公式中的 $in_size 需要)!
    • 你甚至可以在 1 行中做到这一点stackoverflow.com/a/66901038/1597158
    • 谢谢!它就像一个魅力!如果您添加选项-background none,您还将拥有一个透明背景的.png!
    【解决方案9】:

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

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

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

    【讨论】:

      【解决方案10】:

      对于简单的 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]
      

      【讨论】:

      • 在 Windows 10 上为我崩溃:将 cairocffi 导入为 cairo 文件 "c:\program files (x86)\python35-32\lib\site-packages\cairocffi_init_. py",第 39 行,在 cairo = dlopen(ffi, 'cairo', 'cairo-2', 'cairo-gobject-2', 'cairo.so.2') 文件 "c:\program files ( x86)\python35-32\lib\site-packages\cairocffi_init_.py",第 36 行,在 dlopen 中引发 OSError("dlopen() failed to load a library: %s" % ' / '.join(names)) OSError: dlopen() failed to load a library: cairo / cairo-2 / cairo-gobject-2 / cairo.so.2
      • 很好,Ubuntu-19.04 上的 cairosvg 为我完成了这项工作。
      • 我只想写:多么出色的解决方案!第一个 PNG 看起来很棒,但其他的则不然。相反,我必须写:这完全取决于 SVG,哪种解决方案提供最佳质量。
      【解决方案11】:

      你为什么不试试 inkscape 命令行,这是我的 bat 文件,用于将这个目录中的所有 svg 转换为 png:

      FOR %%x IN (*.svg) DO C:\Ink\App\Inkscape\inkscape.exe %%x -z --export-dpi=500 --export-area-drawing --export-png ="%%~nx.png"

      【讨论】:

        【解决方案12】:

        这对我有用,并且是最容易运行的。

        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
        

        【讨论】:

          【解决方案13】:

          透明背景,使用 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
          

          【讨论】:

          • 我很惊讶这个答案如此之低。其他一些方法错误地绘制了我复杂的 SVG,但这很有效。
          • 我不得不使用convert,但除此之外它工作得很好(convert -background none -size x1080 in.svg out.png)。
          【解决方案14】:

          我来到这篇文章 - 但我只想在不使用任何参数的情况下批量快速地进行转换(由于多个文件的大小不同)。

          rsvg drawing.svg drawing.png
          

          对我来说,要求可能比原作者要容易一些。 (想在 MS PowerPoint 中使用 SVG,但不允许)

          【讨论】:

          • 供参考,在macOS上安装时使用brew install librsvg,转换命令为rsvg-convert
          • 在Ubutni也是rsvg-convert,包是librsvg2-bin,输出需要-o drawing.png
          【解决方案15】:

          让我印象深刻的一件事是在输入文件名之后设置-density。那没有用。将其移至 convert 中的第一个选项(在其他任何内容之前)使其工作(对我来说,YMMV 等)。

          【讨论】:

            【解决方案16】:

            如果没有 librsvg,您可能会得到黑色的 png/jpeg 图像。我们必须使用 imagemagick 将librsvg 安装到convert 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
            
            

            【讨论】:

            • 我没有安装这个库,也没有得到黑色图像。
            【解决方案17】:

            在 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
            

            【讨论】:

              【解决方案18】:

              我通过更改<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
              

              【讨论】:

              • 为什么要将计算机生成的图像返回为 jpeg :(?
              【解决方案19】:

              @808sound 的最佳答案对我不起作用。我想调整大小

              得到

              因此,我打开了 Inkscape,然后转到 FileExport as PNG file,然后弹出一个 GUI 框,让我可以设置所需的确切尺寸。

              Ubuntu 16.04 Linux 上的版本: Inkscape 0.91 (September 2016)

              (顺便说一下这张图来自Kenney.nl's asset packs

              【讨论】:

                【解决方案20】:

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

                我们已经看到 answer 中的 72 和 answer 中的 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
                

                按照this forum post 的建议并使用此documentation 进行修改

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

                这是 PixelsPerCentimeter 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)
                

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2015-07-11
                  • 1970-01-01
                  • 2018-10-26
                  • 2012-11-30
                  • 1970-01-01
                  • 2018-08-28
                  • 1970-01-01
                  • 2015-12-02
                  相关资源
                  最近更新 更多