PDF是一种常见的媒体格式,我们常常会有PDF处理的相关需求。Adobe的工具对PDF处理提供了大量的支持,但是因为其缺乏跨平台性,不能很好地在Linux下使用。事实上,有大量跨平台的开源软件具有强大PDF处理功能,本质上国产的一大堆付费的PDF处理工具也基本上都基于这些开源软件。笔者在此介绍部分使用开源命令行工具方便地处理PDF的方法。
相关软件及环境
本博客主要使用GhostScript、Poppler与Imagemagick进行处理。对于Linux环境,大多数发行版的官方软件源应该都收录有这两款软件包,可以直接安装。以Arch Linux为例:
sudo pacman -S ghostscript poppler imagemagick --needed
在Windows平台下,可以选择Windows本地的包管理器安装这些工具,也可以直接在GhostScript、Poppler和Imagemagick的官方网站上下载。由于笔者的Windows系统已经配置了MSYS2环境,可以直接从中使用与Arch Linux类似的pacman命令进行安装,更加方便,以笔者使用的UCRT64平台为例:
pacman -S mingw-w64-ucrt-x86_64-ghostscript mingw-w64-ucrt-x86_64-poppler mingw-w64-ucrt-x86_64-imagemagick --needed
PDF与图片间的转化
从图片生成PDF
注意:自IMv7开始,convert命令被弃用,建议使用magick命令代替,下同。
Imagemagick支持直接从图片转化生成PDF文件。Imagemagick对大量的图片格式均进行了支持,无论是传统的jpg、png等格式,还是较新的webp、heic、jxl等格式,Imagemagick均进行了支持。使用Imagemagick将图片转化为PDF的命令十分简单,基本命令为:
convert 图片1 [图片2...图片3...图片n...] 输出文件.pdf
对于待转化的图片,也有Unix通配符支持,将图片文件根据想要的顺序按照字符串比较先后规则命名好后(即注意"9" > "100",命名编号数字均应当用0补足"0009" < "0100"),可以用*.文件后缀名匹配所有图片文件,例如:
convert *.png output.pdf
这将会把当前文件夹下的所有以.png结尾的文件转化输出到output.pdf中。
在Windows平台下,为了避免与内建命令发生冲突,应当把convert写成绝对路径。
将PDF转化为图片
使用Imagemagick的convert命令也可以将PDF文件转化为图片,基本语法如下:
convert -density [像素密度] 源文件.pdf [目标文件名].[目标后缀名]
由于默认情况的像素密度太低,为了得到正常清晰度的图片,这里必须要用-density指定像素密度参数,高清晰度要求可以设置为600,一般清晰度要求200即可。对于多页的PDF,该命令会自动生成以[目标文件名]-数字后缀.[后缀名]命名的一组图片。
此外,如果想将PDF的所有页面合并为一张长图,可以使用-append参数,命令如下:
convert -density [像素密度] 源文件.pdf -append [目标文件名].[目标后缀名]
由文字PDF得到纯图PDF
使用Imagemagick还可以将含有文字的PDF转化为位图PDF,可以有效避免部分复制行为,保护PDF内容:
convert -density [像素密度] 源文件.pdf [目标文件名].pdf
与上一小节类似,这里也需要手动传递-density参数指定像素密度。此外,通过-density参数的设置,该方法还能用于降低纯图PDF的像素密度,一定程度上起到控制文件体积的效果。
此外,利用GhostScript还可以实现更加强大的功能,将嵌入了文字的PDF转化为矢量图PDF,在抹除文字的同时还能保证内容清晰度没有损失,使用命令:
gs -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -dNoOutputFonts=true -sOutputFile=[目标文件].pdf [源文件].pdf
由于该方法是将文字内容直接转化为矢量图形,因此不会有像素密度的问题,生成的PDF在任意缩放下均能保证清晰度,不会出现锯齿等问题。笔者更推荐使用该方法来生成无文字PDF。
PDF文件体积压缩
我们在将大量.png等压缩率不够高的图片转化为PDF时,或者在某些情况下直接由文字或网页内容直接转化为PDF时,常常会得到体积过大的PDF文件,这些大体积文件在存储及传输中均会带来不便,我们往往需要考虑使用合理方法来减小其体积。降低分辨率是减小PDF文件体积的一种手段,然而这种手段对于直接由文字生成的全矢量图形式PDF并没有效果,而且也可能会造成阅读体验的下降。因此,PDF文件体积压缩最好通过PDF内建的压缩功能进行。
使用GhostScript可以对PDF文件进行压缩,可以使用以下基本命令:
gs -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -dQUIET -dCompatibilityLevel=1.73 -sOutputFile=[目标文件].pdf [源文件].pdf
其中,-dCompatibilityLevel用于设置PDF的压缩等级,1.73为允许的最大值。该压缩功能十分强大,在原PDF内容压缩很不充分时,甚至可以实现1/10到1/20的压缩率。
此外,这一功能不仅可以用于PDF压缩,还可以用于解除PDF的打印或复制密码(但是如果有内容阅读级别的加密依然不能解除)QwQ。具体原理是GhostScript在这里会解析PDF的全部内容,再将内容压缩到新的PDF文件中,而打印或复制密码等元信息并不会在新文件中加入,因此打印或复制密码也就被解除了。这同时也说明通过密码来保护PDF内容不被复制是完全不可靠的,想要更好地保护内容的可复制性还是需要转化为纯图PDF才行。另外,PDF内容阅读级别的加密是直接对PDF本身内容进行了加密,如果没有密码,GhostScript根本无法解析PDF文件的内容,当然也就不能生成绕过密码的新文件了。
PDF分割
PDF分割可以轻松使用GhostScript来实现,使用命令:
gs -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -dFirstPage=[起始页码] -dLastPage=[终止页码] -sOutputFile=[输出文件].pdf [源文件].pdf
其中,-dFirstPage和-dLastPage用于指定起始页码和终止页码。需要注意的是,页码是从1开始的,而不是从0开始的。
PDF分割功能还可以使用另外的pdftk软件来实现,CLI相对更简洁,在Arch Linux下,运行安装命令:
sudo pacman -S pdftk
然后即可使用PDF分割命令:
pdftk [源文件] cat [起始页码]-[终止页码] output [输出文件]
PDF合并
PDF合并可以使用pdfunite命令,这一命令由poppler软件包提供,使用命令:
pdfunite [待合并文件或者通配符] [输出文件]
PDF合并同样也可以用pdftk软件包,基本使用命令为:
pdftk [待合并文件或者通配符] cat output [输出文件]
PDF转化为文本
PDF转化为文本可以使用pdftotext命令,这一命令由poppler软件包提供,使用命令:
pdftotext [源文件] [输出文件]
如果不指定输出文件,pdftotext会将文本输出到标准输出中。
给PDF添加嵌入文字
部分扫描的PDF文件中没有文字层,导致无法搜索和复制文字内容。可以使用ocrmypdf工具给PDF添加嵌入文字层,从而实现可搜索和可复制的PDF文件。有关ocrmypdf的使用,请参考笔者的另一篇文章。