esXGray功能解析01:全自动漂白PDF,使用PyMuPDF替换PDF中所有图片

esXGray可以用来直接漂白一份PDF中的所有图片,之前漂白PDF全文图片的功能有些问题,今日换了一种实现方式,核心思路如下:

  1. 遍历所有图片记录bbox信息
  2. 删除所有图片
  3. 将图片按顺序添加到PDF中实现替换功能

前面在网上搜索良久,代码都有一些问题,不够完美,今日几经修改,目前效果还比较完美,测试了一些文件,操作结果符合预期,包括一些半透明图片。上代码如下:

import fitz
def replace_images3(input_pdf, output_pdf, image_list):
    pdf = fitz.open(input_pdf)  # 读取图片
    img_id = 0
    bbox_dic = {}
    for page in range(len(pdf)):
        bbox_dic[page] = []
        for img in pdf.get_page_images(page):
            if not pdf[page].get_image_bbox(img[7]).isEmpty:
                bbox_dic[page].append(pdf[page].get_image_bbox(img[7]))  # 将位置信息存入dict
                pdf._deleteObject(img[0])  # 删除图片

    for page in range(len(pdf)):
        for i in range(len(bbox_dic[page])):
            bbox = bbox_dic[page][i]  # 取出位置
            fn = image_list[img_id]  # 从list中取出新图文件名
            pdf[page].insert_image(bbox, filename=fn)  # 根据文件名插入图片
            img_id += 1

    pdf.save(output_pdf)  # 保存

  测试代码如下:

img_path = "C:\\Users\\eerso\\Desktop\\PDF_PNG\\output\\"
imgs = []
# 下面代码手动生成imgs图片文件列表
for n in range(1, 4):
    imgs.append(img_path + str(n) + '.png')
imgs.append(img_path + '4.jpeg')
replace_images3(r"C:\Users\eerso\Desktop\PDF_PNG\new.pdf", r"C:\Users\eerso\Desktop\PDF_PNG\new_x.pdf", imgs)

上面的代码已知缺陷:如果图片有旋转,替换后的图片尺寸会变大且没有旋转,还需要再修改,目前还在研究中…… 2023/7/12

2023/7/17 找到了解决方案参考 https://blog.csdn.net/Crazy_zh/article/details/105346653  可以直接更新pdf中图片数据流

 

def pdf_rep(pdf_in, pdf_out, img_path):
    """可以正常替换图像数据流,但需要确定图片格式jpeg,png,..."""
    import PyPDF4
    from io import BytesIO
    from PIL import Image

    pdf_src = PyPDF4.pdf.PdfFileReader(pdf_in)
    pdf_ret = PyPDF4.pdf.PdfFileWriter()
    for i in range(0, pdf_src.getNumPages()):
        page = pdf_src.getPage(i)
        try:
            obj = page['/Resources']['/XObject']
            for j in obj:
                img = obj[j].getData()
                with Image.open(img_path) as img:
                    stream = BytesIO()
                    img.save(stream, 'png') # 此处应根据图片格式不同而不同
                    new_image_data = stream.getvalue()
                obj[j].setData(new_image_data)
                # 上面代码中的obj[j]是一个EncodedStreamObject的实例,在PyPDF4 1.27.0
                # 版本中,EncodedStreamObject类中的setData方法并未实现。此版本的发布时间是18年8月,很可能不会再更新了。
                #
                # 最简单的修改方法:
                # 打开PyPDF4模块中的generic.py
                # 找到EncodedStreamObject类中的setData方法
                # 将方法中的原有代码注释,添加self._data = data
        except KeyError as e:
            print(f'KeyError:第 {i+1} 页无图')
        pdf_ret.addPage(page)
    with open(pdf_out, 'wb') as f:
        pdf_ret.write(f)

 

  

 

posted @ 2023-07-11 17:31  Moneky  阅读(880)  评论(0)    收藏  举报