学过计算机的小伙伴们都知道 ,计算机中用 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的信息结构损坏了,不能复制文字了。