如何将PyPDF4修改PDF黑色对象颜色的代码迁移到pypdf 3.6.0?
迁移PyPDF4到pypdf 3.6.0:PDF黑色对象转红色实现指引
核心逻辑说明
pypdf 3.x版本对PDF内容流的操作机制和PyPDF4差异明显,不能直接沿用旧版的字符串替换或简单流操作,必须通过解析内容流的指令单元,针对性替换颜色设置指令,再重新绑定到页面。
具体实现步骤
1. 导入依赖模块
from pypdf import PdfReader, PdfWriter from pypdf.generic import ContentStream, NameObject, NumberObject
2. 编写颜色替换函数
遍历内容流的每一组指令,识别所有设置黑色的操作(包含RGB模式和灰度模式的填充、描边色),替换为红色设置指令:
def replace_black_with_red(content_stream): new_operations = [] # 遍历内容流的所有指令对(操作数列表 + 操作符) for operands, operator in content_stream.operations: # 替换RGB填充黑色(指令rg) if operator == b"rg" and operands == [NumberObject(0), NumberObject(0), NumberObject(0)]: new_operations.append(([NumberObject(1), NumberObject(0), NumberObject(0)], b"rg")) # 替换RGB描边黑色(指令RG) elif operator == b"RG" and operands == [NumberObject(0), NumberObject(0), NumberObject(0)]: new_operations.append(([NumberObject(1), NumberObject(0), NumberObject(0)], b"RG")) # 替换灰度填充黑色(指令g),转为RGB红色填充 elif operator == b"g" and operands == [NumberObject(0)]: new_operations.append(([NumberObject(1), NumberObject(0), NumberObject(0)], b"rg")) # 替换灰度描边黑色(指令G),转为RGB红色描边 elif operator == b"G" and operands == [NumberObject(0)]: new_operations.append(([NumberObject(1), NumberObject(0), NumberObject(0)], b"RG")) # 非颜色设置指令直接保留 else: new_operations.append((operands, operator)) # 用新指令重新构建内容流 return ContentStream(new_operations, content_stream.pdf)
3. 处理PDF并生成输出
读取源PDF的每个页面,替换内容流后绑定到页面,最终写入输出文件:
def process_pdf(input_file, output_file): reader = PdfReader(input_file) writer = PdfWriter() for page in reader.pages: # 解析当前页面的内容流 original_stream = ContentStream(page["/Contents"], reader) # 执行颜色替换 modified_stream = replace_black_with_red(original_stream) # 将修改后的内容流重新绑定到页面 page[NameObject("/Contents")] = modified_stream # 添加处理后的页面到写入器 writer.add_page(page) # 写入最终PDF文件 with open(output_file, "wb") as f: writer.write(f) # 调用示例 process_pdf("source.pdf", "red_output.pdf")
关键差异提示
- PyPDF4中直接操作ContentStream字符串的方式在pypdf 3.x中不再适用,必须通过
operations属性拆解指令单元。 - 页面内容流的赋值需要通过
NameObject("/Contents")明确指定,确保修改后的内容被页面正确识别。 - 字符串替换容易因PDF内容流压缩、指令拆分等问题失效,解析指令的方式才是可靠方案。
内容的提问来源于stack exchange,提问作者Albin Dennevi
相关产品推荐
相关产品推荐

