将PDF转换为PNG

93

我正在尝试将PDF转换为PNG图像(至少是其中的封面)。我已经成功地使用pdftk提取了PDF的第一页。我正在使用imagemagick进行转换:

convert cover.pdf cover.png

这个方法能够运行,但不幸的是 cover.png 文件渲染出现了问题(PDF文件中一些alpha对象没有被正确地渲染)。 我知道 ImageMagick 使用 GhostScript 进行转换,如果我直接使用 gs 命令就可以得到所需的结果,但我宁愿使用 convert 库,因为它有其他工具我想要利用。

以下是 GhostScript 中的命令,可以得到所需的图像:

gs -sDEVICE=pngalpha -sOutputFile=cover.png -r144 cover.pdf

我想知道是否有办法通过将参数传递到GhostScript来进行转换,还是只能直接调用GhostScript?


3
直接调用GhostScript为什么是个问题? - kquinn
这真的不是什么大问题。我想同时运行一些其他参数通过转换,如果我能保持所有在一个命令中,那就太好了。这可以使我的代码更加清晰和一致。这也意味着少一个临时文件。 - Adam
你如何调用gs和ImageMagick如何调用它之间有什么区别?值得向ImageMagick上游报告一些问题(注意更新ghostscript也可能有所帮助...) - rogerdpack
我在使用pdftoppm时运气最佳:https://askubuntu.com/a/50180/951756 - SurpriseDog
12个回答

75

如果第一个命令可以将其输出写入标准输出,而第二个命令可以从标准输入读取其输入,则可以使用一个带有两个命令(gsconvert)的命令行,这两个命令通过管道连接。

  1. 幸运的是,gs可以写入标准输出(... -o %stdout ...)。
  2. 幸运的是,convert可以从标准输入中读取(convert -background transparent - output.png)。

问题解决:

  • GS用于处理特殊图像的Alpha通道,
  • convert用于创建透明背景,
  • 使用管道避免在磁盘上写出临时文件。

完整解决方案:

gs -sDEVICE=pngalpha       \
   -o %stdout              \
   -r144 cover.pdf         \
   |                       \
convert                    \
   -background transparent \
   -                       \
    cover.png

更新

如果您想每个PDF页面都有一个单独的PNG,请使用%d语法:

gs -sDEVICE=pngalpha -o file-%03d.png -r144 cover.pdf

这将创建名为page-000.pngpage-001.png等的PNG文件(注意,%d计数是从0开始的--file-000.png对应于PDF的第1页,001对应于第2页...)

或者,如果您想要保留透明背景,在一个有100页的PDF中,执行以下操作:

for i in {1..100}; do        \
                             \
  gs -sDEVICE=pngalpha       \
     -dFirstPage="${i}"      \
     -dLastPage="${i}"       \
     -o %stdout              \
     -r144 input.pdf         \
     |                       \
  convert                    \
     -background transparent \
     -                       \
      page-${i}.png ;        \
                             \
done

7
只有在我将-dBATCH -dNOPAUSE -dQUIET添加到gs选项中时,才能使其正常工作。 - ford
1
@ford:那意味着你使用的是旧版本的Ghostscript。最近的版本可以使用"-o output.file",这同时还自动静默地设置了"-dBATCH -dNOPAUSE -dQUIET"。 - Kurt Pfeifle
工作对我来说很好,但我想自动将多页pdf转换为image_1.png、image_2.png等。这在一个命令中是否很容易?我应该先从pdf文件中提取每一页吗? - Tarass
是的,谢谢。为了避免页面数量问题,我更喜欢在同一个脚本中使用您的第一个更新和这个命令:"for i in ls file-*.png | sort; do convert $i -transparent white $i done"。 - Tarass
如果您无法控制输入文档,请务必设置“-dSAFER”。 - mlissner
显示剩余4条评论

34

在所有可用的替代方案中,我发现Inkscape在将PDF转换为PNG时能够产生最精确的结果。特别是当源文件具有透明层时,Inkscape可以成功地完成转换,而Imagemagick和其他工具则失败了。

这是我使用的命令:

inkscape "$pdf" -z --export-dpi=600 --export-area-drawing --export-png="$pngfile"

这是实现脚本的代码:

#!/bin/bash

while [ $# -gt 0 ]; do

pdf=$1
echo "Converting "$pdf" ..."
pngfile=`echo "$pdf" | sed 's/\.\w*$/.png/'`
inkscape "$pdf" -z --export-dpi=600 --export-area-drawing --export-png="$pngfile"
echo "Converted to "$pngfile""
shift

done

echo "All jobs done. Exiting."

1
请注意,--export-png 现已弃用。如果导出类型可以从文件名中推断出来,请使用 --export-filename="$pngfile",否则请使用 --export-filename="$pngfile" --export-type="png" 显式指定导出类型。 - Alexis

26

使用以下命令将pdf转换为图像文件:

对于PNG gs -sDEVICE=png16m -dTextAlphaBits=4 -r300 -o a.png a.pdf

对于JPG gs -sDEVICE=jpeg -dTextAlphaBits=4 -r300 -o a.jpg a.pdf

如果您有多个页面需要添加到名称中%03d gs -o a%03d.jpg a.pdf

每个选项的含义如下:

  • sDEVICE={jpeg,pngalpha,png16m...} - 文件类型
  • -o - 输出文件(%stdout表示标准输出)
  • -dTextAlphaBits=4 - 字体抗锯齿。
  • -r300 - 300 dpi

1
有用的答案,但不是针对这个问题... - Michel de Ruiter

13

您还可以使用包含在poppler-utils软件包中的命令行实用程序:

sudo apt-get install poppler-utils
pdftoppm --help
pdftocairo --help

例子:

pdftocairo -png mypage.pdf mypage.png

1
非常好。如果PDF有多页,将会生成多个PNG文件。 - Tomasz Gandor
对于 macOS,请使用 brew install poppler - Ashutosh Jindal

9
无法使用已接受的答案使其正常工作。后来发现实际上解决方案更简单,因为Ghostscript不仅本地支持PNG,甚至还支持多种不同的“编码方式”(参见此处):

  • png256
  • png16
  • pnggray
  • pngmono
  • ...

对我有效的 shell 命令是:

gs -dNOPAUSE -q -sDEVICE=pnggray -r500 -dBATCH -dFirstPage=2 -dLastPage=2 -sOutputFile=test.png test.pdf

它将使用pnggray编码和500 DPI将test.pdf的第2页保存为test.png。


1
这个很有效。作为一个小的补充,我想添加一个"%d"到输出中,以便每页创建一个新文件。这使得命令看起来像这样:gs -dNOPAUSE -q -sDEVICE=pnggray -r500 -dBATCH -dFirstPage=2 -dLastPage=5 -sOutputFile=output%d.png input.pdf - Betaminos

3

由于本页面还列出了替代工具,我会提到 xpdf,它已经为Linux / Windows / Mac编译好了命令行工具。支持透明度。可以免费用于商业用途 - 与 Ghostscript 定价“真是太离谱”相反。

在处理大型PDF文件的测试中,它比Ghostscript快了7.5%。

(它还有PDF转文本和HTML转换器)


我现在已经使用了一段时间,它的表现非常好。总体来说,在更高的分辨率下,它比Ghostscript慢一些。但是图像看起来更漂亮(虽然有点暗),而且在xpdf中可以很好地实现抗锯齿,而在Ghostscript中无法实现! - TheStoryCoder

1

我会加入我的解决方案,即使这个帖子是旧的。也许这仍然会对某些人有所帮助。

首先,我需要生成PDF。我使用XeLaTeX 来实现:

xelatex test.tex

现在,ImageMagickGraphicMagic都从左到右解析参数,因此最左边的参数将首先被执行。我最终使用了这个顺序来实现最佳处理:

gm convert -trim -transparent white -background transparent -density 1200x1200 -resize 25% test.pdf test.png

它在透明背景上提供了漂亮的图形,裁剪到实际页面上的内容。使用 -density-resize 参数可以获得更好的粒度和增加整体分辨率。

我建议您检查一下是否可以减少密度。这将缩短转换时间。


1
尝试提取单个页面。

$page = 4

gs -sDEVICE=pngalpha -dFirstPage="$page" -dLastPage="$page" -o thumb.png -r144 input.pdf

1

对于ImageMagick处理出现色差的PDF文件,我发现GraphicsMagick能够更好地完成这项工作:

$ gm convert -quality 100 -thumbnail x300 -flatten journal.pdf\[0\] cover.jpg

信息不足,但可能是由于颜色空间定义不正确。请查看-colorspace IM选项。 - rivimey

0

您可以使用ImageMagick而无需使用其他工具来分离PDF的第一页。只需执行以下操作:

convert -density 288 cover.pdf[0] -resize 25% cover.png


这里我将名义密度增加了400%(72*4 = 288),然后通过1/4进行调整大小(25%)。这样可以为生成的PNG提供更好的质量。

但是,如果PDF是CMYK,则PNG不支持。需要将其转换为sRGB,特别是如果具有透明度,因为Ghostscript无法处理带有alpha的CMYK。

convert -density 288 -colorspace sRGB -resize 25% cover.pdf[0] cover.png

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接