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

使用fitz(PyMuPDF)实现PDF半透明叠加失败求助

修复损坏笔记PDF:原PDF与笔记PDF叠加实现半透明笔记

问题背景

在iPad上给PDF添加笔记后,应用崩溃前保存的新PDF损坏,修复后仅保留高亮和手写笔记,原PDF内容丢失。尝试用PyMuPDF(fitz)将原PDF与笔记PDF以50%透明度叠加,但笔记页面的空白区域会遮挡原PDF,最终只能看到空白背景上的笔记。

原测试代码

import fitz  # PyMuPDF 
journal_document = fitz.open(journal_path) # type: ignore 
notes_document = fitz.open(notes_path) # type: ignore 
combined_document = fitz.open() # type: ignore

for page_num in range(len(journal_document)):
    
    if page_num<276:
        continue
    
    # load pages to overlay
    journal_page = journal_document.load_page(page_num)
    notes_page = notes_document.load_page(page_num) 
    
    # extract bottom image 
    journal_pix = journal_page.get_pixmap()
    journal_image = fitz.Pixmap(journal_pix, 0)
    
    # create a new page in output doc
    combined_page = combined_document.new_page(width=journal_page.rect.width,
    height=journal_page.rect.height)
    combined_page.show_pdf_page(journal_page.rect, journal_document, page_num)
    
    # extract notes to be overlayed 
    notes_pix = notes_page.get_displaylist().get_pixmap()
    notes_image = fitz.Pixmap(notes_pix)
    notes_image.set_alpha(bytearray(int(128)) * 595 * 842)
    
    # Insérer l'image du journal sur la nouvelle page
    combined_page.insert_image(notes_page.rect, stream=notes_image.tobytes(), 
    alpha = int(128))
    
    print(f"page {page_num} saved...")
    
    break

combined_document.save(output_path)

修复方案

原代码的问题在于将整个笔记页面转成图片后设置全局透明度,笔记页面的空白区域会以半透明白色覆盖原PDF,导致原内容被遮挡。正确做法是只让笔记元素(高亮、手写)带透明度,空白区域完全透明。

修改后的单页测试代码

import fitz  # PyMuPDF

# 替换为实际文件路径
journal_path = "原PDF文件路径.pdf"
notes_path = "仅含笔记的PDF文件路径.pdf"
output_path = "合并后的PDF文件路径.pdf"

journal_doc = fitz.open(journal_path)
notes_doc = fitz.open(notes_path)
combined_doc = fitz.open()

# 测试处理第276页
page_num = 276
journal_page = journal_doc.load_page(page_num)
notes_page = notes_doc.load_page(page_num)

# 创建新页面,先绘制原PDF内容
combined_page = combined_doc.new_page(
    width=journal_page.rect.width,
    height=journal_page.rect.height
)
combined_page.show_pdf_page(journal_page.rect, journal_doc, page_num)

# 遍历笔记页面的显示列表,仅处理笔记元素
display_list = notes_page.get_displaylist()
for item in display_list:
    # 只保留手写/高亮路径、文本笔记元素
    if item.type in (fitz.PDF_DRAW_PATH, fitz.PDF_DRAW_TEXT):
        # 设置元素透明度为50%(0.5对应0-1范围)
        item.set_opacity(0.5)
        # 将元素绘制到合并页面
        combined_page.draw_displaylist(item)

combined_doc.save(output_path)
print(f"第{page_num}页处理完成,已保存至{output_path}")

批量处理所有页面代码

import fitz  # PyMuPDF

journal_path = "原PDF文件路径.pdf"
notes_path = "仅含笔记的PDF文件路径.pdf"
output_path = "合并后的PDF文件路径.pdf"

journal_doc = fitz.open(journal_path)
notes_doc = fitz.open(notes_path)
combined_doc = fitz.open()

for page_num in range(len(journal_doc)):
    journal_page = journal_doc.load_page(page_num)
    notes_page = notes_doc.load_page(page_num)
    
    # 创建新页面并绘制原PDF内容
    combined_page = combined_doc.new_page(
        width=journal_page.rect.width,
        height=journal_page.rect.height
    )
    combined_page.show_pdf_page(journal_page.rect, journal_doc, page_num)
    
    # 处理笔记元素
    display_list = notes_page.get_displaylist()
    for item in display_list:
        if item.type in (fitz.PDF_DRAW_PATH, fitz.PDF_DRAW_TEXT):
            item.set_opacity(0.5)
            combined_page.draw_displaylist(item)
    
    print(f"第{page_num}页处理完成")

combined_doc.save(output_path)
print(f"所有页面处理完成,已保存至{output_path}")

关键说明

  • 直接操作笔记页面的显示列表元素,而非将整页转成图片,避免空白区域遮挡原PDF。
  • 过滤显示列表中的非笔记元素,仅保留手写/高亮路径(PDF_DRAW_PATH)和文本笔记(PDF_DRAW_TEXT)。
  • 给每个笔记元素单独设置透明度,确保笔记半透明显示在原PDF内容之上。

内容的提问来源于stack exchange,提问作者Hadriensz

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 07:33:20