Skip to content

「工具」使用 Python 脚本自动裁切 PDF 白边,提升电子书阅读体验

Published at:

起因

如果你在 Kindle 等小屏设备上看 PDF 电子书,应该有过这样的烦恼:
书页四周留着大块空白,而这种老一点的设备并不支持缩放功能;即使支持,频繁缩放、拖动也会让阅读体验大打折扣。

于是我想,能不能借助一个脚本:

  • 可以裁切 PDF 的页边;
  • 支持奇偶页不同的边距裁切(很多扫描版书籍奇偶页边不同)。

于是就写了这个小工具——CutEBookMargin(在 GPT 的帮助下)。项目链接:CutEBookMargin

核心功能

1. 自动分析白边

通过 --analyze 参数指定需要分析白边的页码,支持离散页面和连续页面,目标是找出 PDF 页面有效内容的最小包围盒,然后把它转成可以直接用于裁剪的边距值。实现过程分为几步:

  1. 将指定页栅格化(Rasterize):以 200 的 dpi 将页面渲染成位图。

  2. 转换为灰度图并二值化 : 如果是彩色/灰度 PDF,都统一转成灰度矩阵;使用亮度阈值 _WHITE_THRESH = 245 区分“空白像素”和“内容像素”。阈值略低于纯白(255),可以容忍轻微的扫描底色或纸张纹理。

  3. 扫描非空白区域 :用 numpy.where() 分别找出有内容的行和列索引。第一行/最后一行非空像素对应的就是内容区上下边界,同理左右边界。

  4. 安全边距 :在四个方向各留 6 pt 作为安全边距,避免裁到文字或页码。

  5. 多页聚合 :先得到每页的 {left, top, right, bottom},再按 10% 分位数(p10)聚合成推荐值,能有效避免单页异常值的干扰。 同时会分别计算奇数页和偶数页的推荐值,以应对左右版心不同的扫描书。

最终,程序会打印统一边距和奇偶页边距两种方案,直接给出可以运行的命令。

使用示例:

bash
python run.py -i "book.pdf" --analyze 8-11,13

这样程序会检测第 8 到第 11 页,以及第 13 页的边距,然后会给出类似于下面的推荐指令:

text
Analyzed pages (1-based): 8, 9, 10, 11, 13
Suggested uniform margins (pt): left=38.0, top=52.0, right=38.0, bottom=50.0

Paste to crop (uniform):
python run.py -i book.pdf -o book.trimmed.pdf -m 38.0,52.0,38.0,50.0
(to add page numbers: append --numbers --num-from 1 --num-pos br|bc|bl)

Suggested odd/even margins (pt): odd=38.0,52.0,38.0,50.0 | even=36.0,51.0,39.0,50.0

Paste to crop (odd/even):
python run.py -i book.pdf -o book.trimmed.pdf --odd 38.0,52.0,38.0,50.0 --even 36.0,51.0,39.0,50.0
(to add page numbers: append --numbers --num-from 1 --num-pos br|bc|bl)

2. 裁切页面

直接复制分析得到的推荐大小和指令,也可以手动微调四个方向裁切掉的大小。
在裁切的同时,可以加上 --numbers 参数为页面添加页码。这样做有两个好处:

  • 有的扫描书籍原本就没有页码,添加后方便引用和查找;
  • 有些书的页码位置占用过多空间,我希望手动裁切掉原来的页码,替换成更小巧紧凑的新页码。

下面这个例子使用了奇偶页不同的边距,并且从第 2 页开始编号,页码放在底部居中位置(bc):

bash
python run.py -i book.pdf -o book.trimmed.pdf \
    --odd 38.0,52.0,38.0,50.0 \
    --even 36.0,51.0,39.0,50.0 \
    --numbers --num-from 2 --num-pos bc

最终效果