- 图形学
- 图像处理
【免费下载链接】mupdf
mupdf mirror
MuPDF 提供了一组统一的“PDF 写入选项”(PDF Write Options),用于精细控制所有 PDF 写出函数的输出行为:流的压缩与解压、对象垃圾回收、内容流清理、加密与密码策略、增量更新等。本指南以 docs/reference/common/pdf-write-options.md 为骨架,结合仓库中 source/pdf/pdf-write.c 的解析实现与 source/tools/pdfclean.c 的命令行封装,逐项讲解每个选项的语义、默认值、使用场景与底层原理。读完本文,你将能够用一行选项字符串完成 PDF 瘦身、脱密、修复、加固与可复现导出等任务。
选项的载体:Option String 三种语法
MuPDF 中所有接受“PDF 写入选项”的函数,都以一个选项字符串(option string)作为参数,其语法定义见 docs/reference/common/option-strings.md。同一份选项可以用以下三种等价语法之一书写:
- 逗号分隔键值对(经典语法):值可以加双引号以容纳逗号与等号,双引号本身用连续两个双引号转义:
compress,encrypt=aes-256,owner-password="Hello, ""world""!" - URL 查询串语法:以
?开头,特殊字符用%HH十六进制转义:?compress=true&encrypt=aes-256&owner-password=Hello,%20%22world%22%21 - JSON 子集语法:单个 JSON 对象,仅含布尔、数字、字符串与数字数组,反斜杠和双引号用
\转义:{"compress":true,"encrypt":"aes-256","owner-password":"Hello, \"world\"!"}
布尔值的等价写法包括:true/yes/on/enable/1与false/no/off/disable/0,且值为空时按 true 处理(如garbage与garbage=1等价)。
选项速查总表
以下为文档定义的全部写入选项(按功能归类):
| 功能域 | 选项 | 取值/默认 | 作用 |
|---|---|---|---|
| 压缩 | decompress | 布尔 | 解压所有流(但 compress-fonts/images 除外) |
| 压缩 | compress | yes / flate / brotli | 压缩所有流,yes默认为 flate;双层图像用 CCITT Fax,通用数据用 flate |
| 压缩 | compress=flate | — | 用 Flate 压缩流(默认算法) |
| 压缩 | compress=brotli | — | 用 Brotli 压缩流(⚠️ 提议中的 PDF 特性) |
| 压缩 | compress-fonts | 布尔 | 压缩嵌入字体流 |
| 压缩 | compress-images | 布尔 | 压缩图像流 |
| 压缩 | compress-effort | 0–100,默认 0 | 压缩投入的工作量,100 为最大 |
| 排版 | ascii | 布尔 | 二进制流以 ASCII 十六进制编码写出 |
| 排版 | pretty | 布尔 | 对象带缩进美化打印 |
| 排版 | labels | 布尔 | 打印对象标签(标注对象如何从 Root 可达) |
| 内容流 | clean | 布尔 | 美化内容流中的图形命令 |
| 内容流 | sanitize | 布尔 | 净化内容流中的图形命令 |
| 对象 | garbage | 布尔 | 垃圾回收未使用对象 |
| 对象 | garbage=compact | — | 垃圾回收 + 压缩交叉引用表 |
| 对象 | garbage=deduplicate | — | 垃圾回收 + 压缩交叉引用表 + 去除重复对象 |
| 对象 | objstms | 布尔 | 使用对象流与交叉引用流 |
| 保存 | incremental | 布尔 | 以增量更新方式只写变更对象 |
| 保存 | linearize | 布尔 | 为浏览器优化(已不再支持!) |
| 注释 | appearance | yes / all | 只合成缺失的、或全部注释/控件外观流 |
| 错误 | continue-on-error | 布尔 | 保存过程中出错仍继续 |
| 加密 | decrypt | 布尔 | 已废弃:请改用encrypt=none |
| 加密 | encrypt | none/keep/rc4-40/rc4-128/aes-128/aes-256 | 写出加密文档,默认keep |
| 加密 | permissions | 整数 | 加密时授予的文档权限位 |
| 加密 | user-password | 字符串 | 读取文档所需密码 |
| 加密 | owner-password | 字符串 | 编辑文档所需密码 |
| 元数据 | regenerate-id | 布尔,默认 yes | 重新生成文档 ID |
| 元数据 | reproducible | 布尔,默认 no | 尽量让写出结果可复现 |
压缩与解压:控制文件体积的核心选项
decompress会把除字体、图像以外的所有流解压后原样写出,适合排查被压缩流掩盖的语法问题;compress则相反,把全部流压缩:双层(bi-level)图像使用 CCITT Fax 编码,通用数据使用 flate(compress=flate,即默认)。compress=brotli使用 Brotli 算法——注意这是提议中的 PDF 特性,不是 PDF 规范正式成员,兼容性需自行评估(见 source/pdf/pdf-write.c 中compressions枚举:brotli=2、flate=1)。
compress-fonts与compress-images可分别针对字体流、图像流开启压缩;compress-effort=0|percentage(0 为默认,100 为最大)控制压缩投入的计算量,对应写入选项结构体中的compression_effort字段(见 include/mupdf/pdf/document.h),mutool clean -e即映射该参数。
对象布局与可读性:ascii / pretty / labels
ascii:把二进制流做 ASCII 十六进制编码,输出变成纯文本,便于跨平台传输与 diff 查看,代价是体积约翻倍。pretty:对字典、数组等对象做缩进美化打印,生成“人类友好”的 PDF 源码,mutool clean -t/-tt分别对应紧凑与缩进两种风格。labels:为每个对象打印标签,标注它如何从Root对象可达,是调试对象引用关系的好帮手(对应结构体字段do_labels)。
内容流处理:clean 与 sanitize
PDF 页面内容流(content stream)是一段解释型语言。clean将内容流中的图形命令重新排版、规范化书写;sanitize更进一步做净化处理,剔除危险或冗余操作、规范化操作数。两者在安全审计(打开未知来源 PDF 前)、修复畸形内容流时非常实用,分别对应pdf_write_options的do_clean与do_sanitize字段,命令行开关为mutool clean -c / -s。
对象垃圾回收与交叉引用优化
garbage系列解决“PDF 里残留了大量未引用对象”的问题,从源码看其实现分级(source/pdf/pdf-write.c):
garbage(=1):垃圾回收未使用对象;garbage=compact(=2):在回收基础上压缩交叉引用表,让对象重新编号连续;garbage=deduplicate(=3):进一步合并内容完全重复的对象,通常能把多次嵌入的相同字体、图像合并成一份,是mutool clean -ggg背后的机制。
objstms则把对象打包进对象流(Object Streams)并使用交叉引用流(XRef Streams),这是 PDF 1.5 之后进一步压体积的手段;源码中写入器在启用objstms且文档版本低于 1.5 时会自动提升版本号(source/pdf/pdf-write.c)。
保存策略:增量更新与已废弃的 linearize
incremental只把“自上次保存以来发生变化的对象”追加写入文件,而非整体重写,对保留数字签名、快速保存大批量修改至关重要。但并非所有文档都能增量保存:pdf_can_be_saved_incrementally显示,若文档曾触发过修复(repair_attempted)或已执行过脱密红action(redacted),则不允许增量写(source/pdf/pdf-write.c)。
linearize曾用于生成“线性化(web 优化)”PDF 以便边下载边渲染,但文档明确标注no longer supported!,请勿再依赖此选项。
注释外观流:appearance=yes|all
PDF 注释/表单控件需要外观流(appearance stream)才能在阅读器中正确渲染。appearance=yes(或直接appearance)只合成缺失的外观流;appearance=all强制重建全部外观流(源码枚举见 source/pdf/pdf-write.c,命令行对应mutool clean -A / -AA)。对修复“注释在部分阅读器中显示为空白”的 PDF 非常有效。
加密与访问控制:encrypt / permissions / 密码
encrypt支持以下取值(对应PDF_ENCRYPT_*常量,见 source/pdf/pdf-write.c):
| 取值 | 含义 |
|---|---|
none | 写出不加密文档(脱密) |
keep | 保持文档原有加密状态(默认) |
rc4-40 | 40 位 RC4(PDF 1.1 标准加密) |
rc4-128 | 128 位 RC4 |
aes-128 | 128 位 AES |
aes-256 | 256 位 AES |
单独写encrypt(无值)时按 true 处理,等价于rc4-40。permissions=NUMBER是以位掩码表示的文档权限(默认~0即授予全部权限,见 source/pdf/pdf-write.c);user-password是打开文档所需密码,owner-password是编辑/修改权限所需密码,二者均以 UTF-8 存储于opwd_utf8/upwd_utf8字段(长度上限 128)。
注意decrypt已废弃:源码中解析到decrypt会打印警告并建议改用encrypt=none(source/pdf/pdf-write.c)。
元数据可复现性:regenerate-id 与 reproducible
regenerate-id默认开启(yes),每次写出都会重新生成文档的ID条目;关闭后可保留原 ID,便于追踪同一文档的演化。reproducible默认关闭,开启后写入器在文件头注释中不再写出 MuPDF 版本号(source/pdf/pdf-write.c),配合关闭时间戳类元数据,可以让两次导出产生字节级一致的输出——这对自动化测试、构建缓存非常有用。
默认值与底层数据结构
写入选项在 C API 中的载体是pdf_write_options结构体(include/mupdf/pdf/document.h),每个字段对应一个选项。仓库内置了两套预置配置:
pdf_default_write_options:全 0 默认,即不做增量、不压缩、不清理、不加密,permissions为~0(全部权限),见 source/pdf/pdf-write.c;pdf_snapshot_write_options:do_incremental=1且不重新生成 ID,供快照(snapshot)场景专用。
字符串选项到结构体的转换流程为:pdf_parse_write_options→pdf_init_write_options(清零)→pdf_apply_write_options(逐键解析,source/pdf/pdf-write.c)→ 校验无未识别键后返回;解析失败会抛出参数错误。命令行提示文本集中在fz_pdf_write_options_usage(source/pdf/pdf-write.c)。
实战一:mutool clean 命令行用法
mutool clean是这些写入选项最主要的命令行入口,其完整用法见 docs/tools/mutool-clean.md 与 source/tools/pdfclean.c。选项与命令行开关的对应关系如下:
| 写入选项 | 命令行开关 |
|---|---|
decompress | -d |
compress | -z |
compress-fonts | -f |
compress-images | -i |
compress-effort | -e N(0 默认,1 最小,100 最大) |
ascii | -a |
pretty | -t(紧凑)/-tt(缩进) |
labels | -L |
clean | -c |
sanitize | -s |
garbage/ compact / deduplicate | -g/-gg/-ggg |
objstms | -Z |
appearance=yes/ all | -A/-AA |
encrypt=none | -D |
encrypt=算法 | -E rc4-40\|rc4-128\|aes-128\|aes-256 |
owner-password/user-password | -O/-U |
permissions | -P N |
典型示例:
# 垃圾回收并压缩全部流,输出瘦身后的文件 mutool clean -g -z input.pdf output.pdf # 彻底清理:gc + 去重 + 压缩 + 净化内容流 + 压缩字体图像 mutool clean -ggg -z -f -i -s input.pdf output.pdf # 用 AES-256 加密,设置用户密码与所有者密码 mutool clean -E aes-256 -U "readpass" -O "editpass" input.pdf output.pdf # 去掉所有加密(脱密) mutool clean -D input.pdf output.pdf注意mutool clean默认设置了dont_regenerate_id = 1(source/tools/pdfclean.c),即默认不重新生成文档 ID。
实战二:C API 编程调用
在 C 代码中,先解析选项字符串,再调用pdf_save_document写出:
#include "mupdf/fitz.h" #include "mupdf/pdf.h" pdf_write_options opts; pdf_parse_write_options(ctx, &opts, "compress,garbage=deduplicate,encrypt=aes-256," "user-password=readpass,owner-password=editpass"); pdf_save_document(ctx, doc, "output.pdf", &opts);对应的核心 API 声明见 include/mupdf/pdf/document.h:pdf_parse_write_options/pdf_init_write_options/pdf_apply_write_options/pdf_write_document/pdf_save_document。需要把结构体序列化回字符串时可使用pdf_format_write_options。
使用注意事项与已知细节
linearize已失效:选项被保留解析但明确标注不再支持,不要依赖其“浏览器优化”效果。decrypt已废弃:应使用encrypt=none;源码会给出弃用警告。objstms有版本要求:启用时若文档版本低于 PDF 1.5,写入器会自动提升版本(见 source/pdf/pdf-write.c)。- 选项键名不一致需留意:文档与命令行帮助文本均写作
compress-effort,但 source/pdf/pdf-write.c 中实际解析的键名为compression-effort(对应结构体字段compression_effort)。若按文档书写该键被校验拒绝,可尝试源码中的键名;mutool clean -e则不受影响。 - 未知选项会报错:
pdf_parse_write_options在解析完成后会校验是否存在未被识别的键(source/pdf/pdf-write.c),拼写错误的选项不会被静默忽略。 continue-on-error:开启后保存流程遇到错误仍会继续尝试写出剩余内容,适合批量处理脏文件时尽量产出结果,但应意识到输出可能不完整。
总结
PDF 写入选项是 MuPDF 文档写出体系中最常用的一组配置:从compress/garbage系列的文件瘦身,到clean/sanitize/appearance的内容修复,再到encrypt/ 密码 /permissions的安全控制,以及incremental/reproducible的保存策略,全部可以通过一份简洁的选项字符串在mutool clean、C API 乃至其他支持文档写入的入口中复用。结合 pdf-write-options.md、option-strings.md 与 pdf-write.c 阅读,即可对每一项配置做到“知其然,也知其所以然”。
- 图形学
- 图像处理
【免费下载链接】mupdf
mupdf mirror
相关推荐
SumatraPDF 中的 MuPDF PDF 写出选项(pdf-write-options)详解:从 Option String 到 `pdf_save_document` 的完整实战指南
SumatraPDF 中的 MuPDF PDF 写出选项(pdf write options)详解:从 Option String 到 pdf_save_doc
桌面应用文档MuPDF JavaScript API 详解:Font 字体对象从加载、度量到 PDF 嵌入的完整实践指南
MuPDF JavaScript API 详解:Font 字体对象从加载、度量到 PDF 嵌入的完整实践指南 Font(字体)对象是 MuPDF JavaScr
图形学图像处理SumatraPDF `sumatrapdf-tool clean` 完全指南:压缩、加密、提取与修复 PDF
SumatraPDF sumatrapdf tool clean 完全指南:压缩、加密、提取与修复 PDF sumatrapdf tool clean 是 Su
桌面应用文档
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考