使用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
相关产品推荐
相关产品推荐

