You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用PymuPDF/fitz对PDF中的XObject进行反规范化处理?

PDF XObject反规范化实现(PymuPDF)

以下是使用PymuPDF(fitz)实现XObject反规范化的代码,该代码会将文档中每个XObject的引用替换为独立的XObject副本,消除共享引用:

import fitz
import uuid

def denormalize_xobjects(input_pdf, output_pdf):
    # 打开源PDF和创建输出PDF文档
    src_doc = fitz.open(input_pdf)
    dest_doc = fitz.open()

    for page_idx in range(len(src_doc)):
        src_page = src_doc[page_idx]
        # 创建新页面并复制原页面的所有内容
        dest_page = dest_doc.new_page(width=src_page.rect.width, height=src_page.rect.height)
        dest_page.show_pdf_page(dest_page.rect, src_doc, page_idx)

        # 获取当前页面的所有XObject
        page_xobjects = dest_page.get_xobjects()
        if not page_xobjects:
            continue

        # 解析页面内容流,修改XObject引用
        content_tokens = fitz.Tokenizer(dest_page.read_contents()).tokens()
        modified_tokens = []
        xobj_ref_counter = {}

        i = 0
        while i < len(content_tokens):
            token = content_tokens[i]
            # 识别XObject调用指令:/XObjName Do
            if token == "Do" and i >= 1:
                xobj_name = content_tokens[i-1]
                if xobj_name in page_xobjects:
                    # 为每个引用生成唯一的XObject名称
                    base_name = xobj_name.lstrip('/')
                    if base_name not in xobj_ref_counter:
                        xobj_ref_counter[base_name] = 0
                    xobj_ref_counter[base_name] += 1
                    unique_suffix = f"{xobj_ref_counter[base_name]}_{uuid.uuid4().hex[:8]}"
                    new_xobj_name = f"/{base_name}_{unique_suffix}"

                    # 复制原XObject并添加到页面资源
                    original_xobj = page_xobjects[xobj_name]
                    new_xobj = original_xobj.copy()
                    dest_page.insert_xobject(new_xobj, new_xobj_name.lstrip('/'))

                    # 替换内容流中的XObject名称
                    modified_tokens.append(new_xobj_name)
                    modified_tokens.append(token)
                    i += 2
                    continue
            # 保留非XObject调用的token
            modified_tokens.append(token)
            i += 1

        # 移除原共享XObject,避免残留引用
        for xobj_name in page_xobjects:
            dest_page.set_resource("XObject", xobj_name.lstrip('/'), None)

        # 将修改后的内容流写入页面
        dest_page.write_contents(" ".join(modified_tokens))

    # 保存输出文档
    dest_doc.save(output_pdf)
    # 关闭文档
    dest_doc.close()
    src_doc.close()

# 使用示例
denormalize_xobjects("your_input.pdf", "denormalized_output.pdf")

代码说明

  • 页面复制:先将原页面完整复制到新文档,确保保留所有原始内容和资源。
  • XObject处理:遍历页面内容流中的Do指令,识别所有XObject引用。
  • 副本生成:为每个XObject引用创建独立副本,使用UUID确保名称唯一,避免冲突。
  • 资源更新:将新XObject添加到页面资源,同时移除原共享XObject,确保文档中不再存在共享引用。

内容的提问来源于stack exchange,提问作者W.P. McNeill

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 16:30:30