python 基于PyPDF2 和 reportlab 实现pdf电子文件加盖骑缝章

685 阅读3分钟

基础介绍

骑缝章样式

骑缝章样式.png

从骑缝章图片中确定实现方案: 首先将公章图片进行切割,得到的切片数量对应pdf文件的页数 根据得到的公章切片,生成水印pdf 然后将得到的公章切片水印pdf,合并到pdf文件的每一页当中,实现电子版骑缝章加盖

所以基本的三步就是:公章图片切割、生成水印pdf、合并水印pdf和待处理pdf

pillow

Pillow库是一个Python的第三方库。

在Python2中,PIL(Python Imaging Library)是一个非常好用的图像处理库,但PIL不支持Python3,所以有人(Alex Clark和Contributors)提供了Pillow,可以在Python3中使用。

官方文档路径:pillow.readthedocs.io/en/latest/

公章图片切割需要使用这库

PyPDF2

PyPDF2 是一个纯 Python PDF 库,可以读取文档信息(标题,作者等)、写入、分割、合并PDF文档,它还可以对pdf文档进行添加水印、加密解密等。

官网: pypdf2.readthedocs.io/en/3.0.0/

PyPDF用来读取、合并待处理pdf和生成的水印pdf

reportlab

reportlab是Python的一个标准库,可以画图、画表格、编辑文字,最后可以输出PDF格式。

代码实现

公章图片切割

# 读取公章图片
image = Image.open(image_path)
# 获取公章图片高宽
width, height = image.size
# 读取待处理pdf
pdf = PdfReader(pdf_path)
# 获取待处理pdf页数
pdf_page_count = len(pdf.pages)
# 计算图片宽度除切片数量的余数,用于计算切片宽度时取整
remain_num = image_width % pdf_page_count
# 计算公章切片宽度
split_width = int((image_width - remain_num) / pdf_page_count)

遍历待处理pdf的每一页

# 生成一个pdf文件,作为最终的结果文件
output = PdfWriter()
# 遍历pdf每一页
for index in range(pdf_page_count):
    # index页面的宽度
    pdf_width = int(pdf.pages[index].mediabox.width)
    # index页面的高度
    pdf_height = int(pdf.pages[index].mediabox.height)
    if index == pdf_page_count - 1:
        # 切片起始位置x,y和结束位置x,y,坐标从图片左上角开始
        # 最后一片直接取到图片最右侧,不根据切片宽度
        box = (index * split_width, 0, image_width, image_height)
    else:
        # 切片起始位置x,y和结束位置x,y,坐标从图片左上角开始
        box = (index * split_width, 0, (index + 1) * split_width, image_height)
    # 根据切片坐标获取切片
    region = image.crop(box)
    # 给切片命名
    crop_name = f"./crop_{index}.jpg"
    # 保存切片图片
    region.save(crop_name)

    # 根据切好的公章分片,先生成pdf文件
    watermark_name = f"watermark_{index}.pdf"
    c = canvas.Canvas(watermark_name, pagesize=(pdf_width, pdf_height))
    # at (x, y) with size width height x, y从左下角开始
    position_x = pdf_width - split_width
    position_y = pdf_height / 2 - image_height / 2
    c.drawImage(crop_name, position_x, position_y, split_width, image_height)
    # 保存公章切片pdf
    c.save()
    # 读取公章切片pdf
    watermark = PdfReader(watermark_name, "rb")
    # 读取待处理pdf的页面
    current_page = pdf.pages[index]
    # 合并公章切片和待处理pdf页面
    current_page.merge_page(watermark.pages[0])

    # 将合并后的页面添加到最终结果文件中
    output.add_page(current_page)

    # 将公章切片pdf和图片文件都删掉
    os.remove(watermark_name)
    os.remove(crop_name)
    
    # 切片水印pdf的文件名
    watermark_name = f"watermark_{index}.pdf"
    # 根据index页面的宽度和高度,生成空白的水印pdf文件
    c = canvas.Canvas(watermark_name, pagesize=(pdf_width, pdf_height))
    # at (x, y) with size width height
    # 计算水印添加坐标,x, y从左下角开始
    position_x = pdf_width - split_width
    position_y = pdf_height / 2 - image_height / 2
    # 将公章切片放到坐标位置
    c.drawImage(crop_name, position_x, position_y, split_width, image_height)
    # 保存切片水印pdf
    c.save()
    
    # 读取公章切片pdf
    watermark = PdfReader(watermark_name, "rb")
    # 读取index页面
    current_page = pdf.pages[index]
    # 合并公章切片和待处理pdf页面
    current_page.merge_page(watermark.pages[0])

    # 将合并后的页面添加到最终结果文件中
    output.add_page(current_page)

    # 将公章切片pdf和图片文件都删掉
    os.remove(watermark_name)
    os.remove(crop_name)
    
# 保存最终结果
output.write("output.pdf")