完美版pdf制作小记

需求和方案

最近想学习TCP/IP协议,综合考虑,阅读TCP/IP Illustrated第一版是最好的选择,而且还得是英文版。我有一个电子书阅读器DPT-RP1,找个pdf文件就可以开读了。网络上最流行的英文版pdf,排版质量不佳,插图基本看不清,遂放弃。终于找到一个还不错的版本,制作者给实体书的每一页拍照,然后将图片拼成pdf。这个pdf文件在电脑上阅读效果还不错,但图片的阴影在DPT-RP1里显示出来灰扑扑一片,阅读效果不佳。

于是我考虑把pdf里的每一张图片二值化,只有黑白两种颜色,放到阅读器里,效果应该会不错。我相信,Adobe Acrobat DC或者Photoshop之类的软件一定能够很方便快捷地完成这个任务,但我买不起这些商业软件,安装破解版也很耗费时间和精力。于是搜索了一下免费的解决方案,果然,神通广大的ImageMagick就能完成这项任务,在Linux下就可以搞定。ImageMagick在Linux下的调用命令是convert

拆分pdf文件

首先将pdf文件拆成一张张图片:

1
$ convert -density 300 tcpip.pdf %04d.jpg

其中-density指定PPI值,该值越大,图片越清晰,得到的文件尺寸以及处理时间也会增加。%04d.jpg表示生成的图片文件名用四位数字编号,例如,第123张图片的文件名为0123.jpg

我的机器配置不高,Intel Core i5-4430四核处理器,8G内存。拆分文件相当消耗资源,拆分608页的pdf文件,用完了全部物理内存,耗时大约50分钟。

二值化图片

拆分得到的是彩色图片,要选取一个阈值,将图片二值化,最后得到只有黑白两色的灰度图片。二值化单张图片的命令如下:

1
$ convert 0020.jpg -threshold 55% 0020.png

经过尝试,阈值选择在140(255*55%)附近时,分割效果较好。灰度值大于该阈值的像素全部变为255(白色),灰度值低于该阈值的像素全部变为0(黑色)。

将目录下所有jpg格式的图片二值化,转换后的图片是png格式,文件名后缀由.jpg变为.png,采用下面的脚本实现:

1
2
3
4
5
6
#!/bin/bash

find ./images -name *.jpg | while read fname
do
convert $fname -threshold 55% ${fname%.jpg}.png
done

该项操作耗时不长,在我的机器上,处理608张图片仅花了几分钟。

拼接成pdf文件

最后将png格式的黑白图片拼接成pdf文件,一般的拼接命令如下:

1
$ convert image1.png image2.png image3.png output.pdf

但图片数量较多,为了确保按照文件名的排列顺序拼接,使用如下命令:

1
$ ls *.png | sort -n | tr '\n' ' ' | sed 's/$/\ TCP-IP_Illustrated.pdf/' | xargs convert

该项操作耗时约30分钟。

总结

最后得到的文件类似于高质量的扫描版pdf,阅读效果非常完美,应该是全网最佳版本了。从查找解决方案到制作完成,几乎花费了我整个下午的时间,看来还是商业软件来得方便快捷啊!