学过计算机的小伙伴们都知道 ,计算机中用 RGB 代表红绿蓝,用 (255, 0, 0) 表示红色,(0, 255, 0) 表示绿色,
(0, 0, 255) 表示蓝色,(255, 255, 255) 表示白色,(0, 0, 0) 表示黑色,
去水印的原理就是将水印的颜色变成白色(255, 255, 255)。
首先获取图片宽和高,用 itertools 模块获取宽和高的笛卡尔积作为像素点。
每个像素点的颜色都由 前三位的 RGB 和 第四位的 Alpha 通道构成。Alpha 通道不需要,只要 RGB 数据。
本文用到的库文件
- """
- 安装模块
- pillow
- pymupdf
- pymupdf 可以用 python 访问扩展名为*.pdf、.xps、.oxps、.epub、.cbz或*.fb2的文件。
- 还支持了许多流行的图像格式,包括多页TIFF图像。
- """
-
- from PIL import Image
- from itertools import product
- import fitz
- import os
- import re
- import fnmatch
首先需要通过微信图片截取,确定水印颜色
- def remove_img():
- """
- 去除图片水印
- :return:
- """
- # image_file = input("请输入图片地址:")
- image_file = "water.png"
-
- img = Image.open(image_file)
- width, height = img.size
- """
- product 用于求多个可迭代对象的笛卡尔积(Cartesian Product),它跟嵌套的 for 循环等价.即:
- product(A, B) 和 ((x,y) for x in A for y in B)的效果是一样的。
- >>> A = [1, 2, 3]
- >>> B = [100, 200]
- >>> for item in product(A, B):
- ... print(item)
- (1, 100)
- (1, 200)
- (2, 100)
- (2, 200)
- (3, 100)
- (3, 200)
- """
- for pos in product(range(width), range(height)):
- rgb = img.getpixel(pos)[:3] # 得到图片RGB
- """
- 通过微信图片截取
- 可以看到水印的 RGB 是 (220, 220, 220),这里用 RGB 的和超过 660 就判定是水印点,此时将像素颜色替换为白色。最后保存图片
- """
- if sum(rgb) >= 660:
- img.putpixel(pos, (255, 255, 255))
-
- img.save('eliminate_water.png')
PDF 去水印的原理和图片去水印的原理大致相同,
用 PyMuPDF 打开 pdf 文件后,将 pdf 的每一页都转换为图片 pixmap,
pixmap 有它自己的 RGB,只需要将 pdf 水印中的 RGB 改为(255, 255, 255) 最后保存为图片。
- def remove_pdf():
- """
- PDF 去水印的原理和图片去水印的原理大致相同,
- 用 PyMuPDF 打开 pdf 文件后,将 pdf 的每一页都转换为图片 pixmap,
- pixmap 有它自己的 RGB,只需要将 pdf 水印中的 RGB 改为(255, 255, 255) 最后保存为图片。
- :return:
- """
- page_num = 0
- pdf_file = "water.pdf"
- # 用作提取pdf图片
- pdf = fitz.open(pdf_file);
- # 获得当前路径
- cwd = os.getcwd()
- print(cwd)
- for page in pdf:
- rotate = int(0)
- # 每个尺寸的缩放系数为1.3,这将为我们生成分辨率提高2.6的图像。
- # 此处若是不做设置,默认图片大小为:792X612, dpi=72
- zoom_x = 2 # (1.33333333-->1056x816) (2-->1584x1224)
- zoom_y = 2
- # 设置缩放和旋转系数
- mat = fitz.Matrix(zoom_x, zoom_y).preRotate(rotate)
- pixmap = page.getPixmap(matrix=mat, alpha=False)
- for pos in product(range(pixmap.width), range(pixmap.height)):
- rgb = pixmap.pixel(pos[0], pos[1])
- if sum(rgb) >= 660:
- pixmap.setPixel(pos[0], pos[1], (255, 255, 255))
- pixmap.writePNG(f"{cwd}/water_{page_num}.png")
- print(f"第{page_num}水印去除完成")
- page_num = page_num + 1
图片转 pdf 需要注意的是图片的排序,
用 PyMuPDF 模块打开图片后将图片用 convertToPDF() 函数转成单页的 pdf。插入到新的 pdf 文件中。
- def pic_ConvertPdf():
- """
- 图片转 pdf 需要注意的是图片的排序,
- 用 PyMuPDF 模块打开图片后将图片用 convertToPDF() 函数转成单页的 pdf。插入到新的 pdf 文件中。
- :return:
- """
- pic_dir = os.getcwd()
-
- pdf = fitz.open()
- # pa = re.compile(r'([0-9]+).png')
- # 过滤符合的图片文件
- list_files = [name for name in os.listdir(os.curdir) if fnmatch.fnmatchcase(name, "water_[0-9]*.png")]
- # 按数字排序
- img_files = sorted(list_files, key=lambda x:int((x.split('.')[0]).split('_')[1]), reverse=False)
- # print(img_files)
-
- for file in img_files: # os.listdir返回指定的文件夹包含的文件或文件夹的名字的列表
- print(f"打开{file}开始转换pdf")
- imgdoc = fitz.open(pic_dir + '/' + file)
- pdfbytes = imgdoc.convertToPDF()
- imgpdf = fitz.open("pdf", pdfbytes)
- pdf.insertPDF(imgpdf)
- pdf.save("eliminate_water.pdf")
- pdf.close()
- print(f"pdf水印去除完成,保存为eliminate_water.pdf")
到目前为止水印终于消除了。
可以有一个遗憾,通过此方式消除水印pdf的信息结构损坏了,不能复制文字了。