我的知识记录

Python 批量生成水印 PDF 与图片混合文档教程

用 Pillow + PyPDF2/reportlab 给 PDF 加文字或图片水印,并把多张图片按 A4 排版合并成一个带水印的 PDF,适合合同、发票、扫描件批量处理。

场景痛点

合同、扫描件、产品图要批量出成一份 PDF 发给客户,每页还要加"仅供XX审核"水印。Word/WPS 一份份导出再加水印,上百页要弄半天。用 Python 把图片按 A4 排版拼成 PDF,再叠一层半透明水印文字,一次跑完。

用到的库

pip install Pillow reportlab

完整代码

# -*- coding: utf-8 -*-
# 1) 把多张图片按 A4 排版合成一个 PDF  2) 给整份 PDF 加斜向文字水印
import os
from PIL import Image
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.lib.utils import ImageReader

IMG_EXTS = {".jpg", ".jpeg", ".png", ".bmp", ".webp"}
FONT_PATH = "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf"
# Windows: C:/Windows/Fonts/msyh.ttc

def register_font():
pdfmetrics.registerFont(TTFont("cn", FONT_PATH))

def image_to_pdf_fit(im, page_w, page_h):
"""把一张图按比例缩放到 A4 页面内居中"""
im = im.convert("RGB")
r = min(page_w / im.width, page_h / im.height)
w, h = im.width * r, im.height * r
x = (page_w - w) / 2
y = (page_h - h) / 2
return x, y, w, h

def draw_watermark(c, page_w, page_h, text):
"""在当前页画满斜向半透明水印"""
c.saveState()
c.setFont("cn", 36)
c.setFillGray(0.7)         # 浅灰
c.setFillAlpha(0.25)       # 25% 透明
c.translate(page_w / 2, page_h / 2)
c.rotate(30)
# 在旋转后的坐标系里平铺多行水印
for dy in range(-500, 500, 120):
for dx in range(-400, 400, 350):
c.drawCentredString(dx, dy, text)
c.restoreState()

def make_pdf_with_watermark(input_dir, out_pdf, watermark="仅供内部审核"):
register_font()
page_w, page_h = A4
c = canvas.Canvas(out_pdf, pagesize=A4)

files = sorted(f for f in os.listdir(input_dir)
if os.path.splitext(f)[1].lower() in IMG_EXTS)
for name in files:
with Image.open(os.path.join(input_dir, name)) as im:
x, y, w, h = image_to_pdf_fit(im, page_w, page_h)
c.drawImage(ImageReader(im), x, y, w, h)
draw_watermark(c, page_w, page_h, watermark)
c.showPage()      # 换页
print(f"加页 {name}")

c.save()
print(f"完成 PDF:{out_pdf},共 {len(files)} 页")

if __name__ == "__main__":
make_pdf_with_watermark("./contract_imgs",
"./contract_watermarked.pdf",
watermark="仅供审核使用")

代码讲解

  • reportlab 是 Python 生成 PDF 的标准库,canvas.Canvas 拿到画笔,drawImage 把图片画到页面上,showPage 换页,save 输出文件。
  • 图片按 A4 比例缩放:min(page_w/im.width, page_h/im.height) 保证图不超出页面,居中放。
  • 水印用 translate + rotate 把坐标系搬到页面中心并旋转 30°,再双重循环平铺多行"仅供内部审核",整页都是斜水印。
  • setFillAlpha(0.25) 控制透明度,水印不会盖住正文。
  • 中文水印必须先 pdfmetrics.registerFont(TTFont("cn", 字体路径)),否则 reportlab 默认字体不认中文。

运行结果

把合同扫描件或产品图按页序命名放进 ./contract_imgs,运行后生成 contract_watermarked.pdf,每张图一页 A4,整页铺满 30° 浅灰斜水印,可直接发客户。

注意事项

  • reportlab 默认字体不支持中文,必须注册一个中文 ttf,否则水印会出方块。
  • 图片太大时 PDF 文件会很大,可先用 Pillow 把图缩到 150dpi 再画。
  • 水印透明度别低于 0.15,否则打印出来看不见;别高于 0.4,否则盖字。
  • 已有 PDF 要加水印,用 PyPDF2.PdfWriter 把水印页和原 PDF 合并,思路相同。

Python 批量生成水印 PDF 与图片混合文档教程

标签:

更新时间:2026-09-14 20:24:57

上一篇:Python 在图片上批量添加文字 水印标题教程

下一篇:Python 批量导出文件夹缩略图预览表 图片墙HTML