最近手上有一份PDF资料,水印太多。非常影响阅读。所以写了一个脚本去掉水印。在两年前我折腾过给PDF增加隐藏的文本,说实话,个人感觉PDF格式还是很复杂的。好在很多PDF常见需求都有无数前人躺过坑。在网上搜了一下找了一个比较靠谱的改了一下

先表明,由于PDF格式的复杂性和水印的多样性。水印情况不一样,处理方式不一样。甚至不同的处理方式对原文件造成的破坏也不一样。如果让一个专家针对特定的文件进行特定的处理肯定可以得到很好的效果,据我记忆所知可以对PDF文件进行追加,给已有对象设置可见性。达到去水印的效果且对文件无任何影响

在找资料的时候我也看到有些小伙伴通过将PDF转换成图片。再采取图片去水印的方式,最后再转换成PDF文件。可以说这种方式可操作性很强,效果也很好,大多数情况能适用,但是对文件有很大的破坏性。emmm, 废话了这么多,说说我遇到的情况吧。该PDF文件有图片水印,且每个图片长宽都固定。所以我找的方案是,找到所有这些长宽的图片,然后隐藏, 解决思路是我先找到一个能够编辑PDF的软件,查看水印由哪些元素组成,总结发现是一些图片

使用PyMuPDF使用代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import fitz
import os


def delete_watermark(src, dst, width=963, height=215):
doc = fitz.open(src)
for page in range(doc.pageCount):
images = doc.getPageImageList(page)

for content in doc[page]._getContents():
c = doc._getXrefStream(content)
for _, _, width, height, _, _, _, img, _ in images:
if width == width and height == height:
c = c.replace("/{} Do".format(img).encode(), b"")
doc._updateStream(content, c)

dir = os.path.dirname(dst)
if not os.path.exists(os.path.dirname(dst)):
os.makedirs(dir)
doc.save(dst)


SRC = "/Users/ficapy/Downloads/pdf"
DST = "/Users/ficapy/Downloads/pdf_handle"

for root, dirs, files in os.walk(SRC):
for file in files:
if not file.endswith("pdf"):
continue
src = os.path.join(root, file)
dst = os.path.join(root.replace(SRC, DST), file)
delete_watermark(src, dst)

最后再次强调,具体情况具体分析,想要做到PDF去水印,大多数情况下稍微编码都是能够做到的,但是期待一份代码能够处理所有的去水印情况是不现实的

参考

How to remove an image from PDF?