
图形学图像处理【免费下载链接】mupdfmupdf mirror项目地址https://gitcode.com/gh_mirrors/mu/mupdf点击查看免费下载本文基于 MuPDF 官方参考文档 PDFPage.rst 展开系统讲解 MuPDF JavaScript API 中PDFPage类型的全部静态常量与实例方法包括页面加载、批注增删改、页面盒子设置、toPixmap页面渲染、Redaction去标识化/涂黑两阶段流程、页面内容流处理与坐标变换等。读完后你可以在mutool run的 JS 环境中独立完成页面级读取、编辑、渲染与敏感信息移除等完整工作流并能对照 source/tools/murun.c 中的 FFI 绑定源码验证每个方法的底层行为。一、PDFPage 在 MuPDF JS API 中的定位PDFPage是 MuPDF JavaScript 绑定中代表 PDF 文档中单个页面的对象类型。根据 PDFPage.rst 的说明PDFPage继承自通用Page类型参见 Page.rst因此所有Page接口如getSize、toDisplayList、run等同样可用PDFPage在其上叠加了 PDF 专属能力该类型没有可直接调用的构造函数。PDFPage实例只能通过调用PDFDocument的Document.prototype.loadPage方法获得且文档中特别注明这一点针对PDFDocument在 C 源码层面所有PDFPage方法都通过 FFI 形式注册到 mujs 解释器中。可以在 source/tools/murun.c 看到完整的注册表js_getregistry(J, fz_page); js_newobjectx(J); { jsB_propfun(J, PDFPage.getObject, ffi_PDFPage_getObject, 0); jsB_propfun(J, PDFPage.getWidgets, ffi_PDFPage_getWidgets, 0); jsB_propfun(J, PDFPage.getAnnotations, ffi_PDFPage_getAnnotations, 0); jsB_propfun(J, PDFPage.createAnnotation, ffi_PDFPage_createAnnotation, 1); jsB_propfun(J, PDFPage.deleteAnnotation, ffi_PDFPage_deleteAnnotation, 1); jsB_propfun(J, PDFPage.createSignature, ffi_PDFPage_createSignature, 0); jsB_propfun(J, PDFPage.update, ffi_PDFPage_update, 0); jsB_propfun(J, PDFPage.applyRedactions, ffi_PDFPage_applyRedactions, 4); jsB_propfun(J, PDFPage.process, ffi_PDFPage_process, 1); jsB_propfun(J, PDFPage.toPixmap, ffi_PDFPage_toPixmap, 6); jsB_propfun(J, PDFPage.getTransform, ffi_PDFPage_getTransform, 0); jsB_propfun(J, PDFPage.setPageBox, ffi_PDFPage_setPageBox, 2); jsB_propfun(J, PDFPage.countAssociatedFiles, ffi_PDFPage_countAssociatedFiles, 0); jsB_propfun(J, PDFPage.associatedFile, ffi_PDFPage_associatedFile, 1); jsB_propfun(J, PDFPage.clip, ffi_PDFPage_clip, 1); } js_setregistry(J, pdf_page);这个注册表同时说明了各方法的实参个数是理解哪些参数可省略的可靠依据。加载页面的入口实现在 source/tools/murun.c 的ffi_Document_loadPage中内部调用fz_load_page页码从 0 开始。一个典型的获取实例的写法是var doc mupdf.Document.openDocument(document.pdf, null) var page doc.loadPage(0) // 返回 PDFPage 实例二、读取页面结构与对象getObject、getAnnotations、getWidgetsgetObjectPDFPage.prototype.getObject()返回该页面对应的底层PDFObject即 PDF 中 Page 字典对象是页面级逃生舱口——拿到它之后即可通过PDFObject字典接口直接读写任意键值参见 PDFObject.rst。var obj page.getObject()源码实现见 source/tools/murun.cffi_PDFPage_getObject直接取出pdf_page结构体中的page-obj并以pdf_keep_obj保留引用因此返回的对象与内部页面保持同一生命周期。getAnnotations返回页面上所有批注组成的数组元素类型为PDFAnnotation。实现source/tools/murun.c通过pdf_first_annot/pdf_next_annot遍历页面对象的/Annots链表逐个构造PDFAnnotationuserdata 压入 JS 数组var annots page.getAnnotations()getWidgets与上类似但只返回表单控件widget 是批注的一个子类。实现source/tools/murun.c调用pdf_first_widget/pdf_next_widget返回的数组元素类型为PDFWidget参见 PDFWidget.rstvar widgets page.getWidgets()批注与控件的完整属性、坐标、内容、矩形等操作可继续查阅 PDFAnnotation.rst。三、批注的创建、删除与更新createAnnotation(type)创建指定类型的空白批注type为 PDF 规范的批注类型字符串如Text、Highlight、Redaction等返回PDFAnnotationvar annot page.createAnnotation(Text)从源码看source/tools/murun.c实现先用pdf_annot_type_from_string把字符串解析为枚举解析失败时得到PDF_ANNOT_UNKNOWN再调用 C 层的pdf_create_annot(ctx, page, type)。也就是说创建批注这一步同时完成了构造批注对象 挂到页面 /Annots两件事。deleteAnnotation(annot)从页面删除一个PDFAnnotation内部调用pdf_delete_annotsource/tools/murun.cvar annots page.getAnnotations() page.deleteAnnotation(annots[0])注意原参考文档示例中写作page.delete(annots[0])这是笔误实际注册的方法名是deleteAnnotation见上文注册表。update()遍历页面上所有批注并执行更新返回值是 boolean只要有任何一个批注因事件、JavaScript 动作或人工编辑而发生了变化就返回true提示宿主程序需要重新渲染该页。底层对应pdf_update_pagesource/tools/murun.cvar updated page.update()在交互式编辑器中这通常与PDFAnnotation的edit/事件回调配合使用编辑结束 - 调page.update()- 根据返回值决定是否触发重绘。四、设置页面盒子setPageBox(box, rect)PDFPage.prototype.setPageBox(box, rect)用于修改页面某一种 box 的尺寸。box是页面盒子类型名rect是新的期望尺寸Rectpage.setPageBox(ArtBox, [10, 10, 585, 832])合法的 box 名称取值。从实现看source/tools/murun.c 调用fz_box_type_from_string名称解析在 source/fitz/document.c 中完成大小写不敏感仅支持以下五种box 名称含义MediaBox页面实际介质纸张/画布大小CropBox显示、打印、绘图所用的默认可见区域BleedBox印刷出血区域TrimBox成品裁切线区域ArtBox艺术内容区域如封面设计区源码中若名称无法识别会得到FZ_UNKNOWN_BOXFFI 层随即抛出invalid page box name错误因此传入非法名称不会静默成功。确认合法后再写入 C 层pdf_set_page_box。五、渲染页面为像素图toPixmap(matrix, colorspace, alpha, renderExtra, usage, box)toPixmap将页面渲染成Pixmap位图是 JS 侧生成缩略图、做预处理deskew、OCR 前处理等的核心入口var pixmap page.toPixmap( mupdf.Matrix.identity, // 变换矩阵 mupdf.ColorSpace.DeviceRGB, // 目标颜色空间 true, // 是否带 alpha 通道 false, // 是否渲染批注与控件 View, // 用途View 或 Print CropBox // 使用的页面盒子 )参数完整说明含默认值参数类型说明默认值matrixMatrix从页面坐标到输出像素的变换矩阵无colorspaceColorSpace输出像素的颜色空间如DeviceRGB、DeviceCMYK无alphaboolean输出的 Pixmap 是否包含 alpha 通道无renderExtraboolean是否渲染批注与表单控件trueusagestring输出目标场景View或PrintViewboxstring使用的页面盒子名CropBox从源码实现source/tools/murun.c可以进一步看清两个细节默认值renderExtra未传时按1true处理usage未传时按Viewbox未传时按FZ_CROP_BOX——与文档声明一致渲染路径分流renderExtra为true时调用pdf_new_pixmap_from_page_with_usage页面内容 批注 控件一起渲染为false时改走pdf_new_pixmap_from_page_contents_with_usage只渲染页面内容流跳过批注层。这两个 C 函数声明于 include/mupdf/pdf/page.h。usage参数对应 PDF 的 Usage 特性设为Print时仅当批注带有Print标志时才会出现在输出中这与mudraw等工具的--print行为一致。六、敏感信息移除applyRedactions 两阶段流程静态常量PDFPage带有一组用于 Redaction去标识化俗称涂黑的静态常量文档标注为 MuPDF.js 平台可用WASM 绑定 platform/wasm/lib/mupdf.ts 中也定义了同样的取值。各常量与 C 层枚举一一对应枚举定义及权威注释在 include/mupdf/pdf/page.h常量值语义PDFPage.REDACT_IMAGE_NONE0完全不处理图片PDFPage.REDACT_IMAGE_REMOVE1图片与涂黑区域相交即使被裁剪则整张移除PDFPage.REDACT_IMAGE_PIXELS2仅把侵入涂黑区域的像素替换为黑色PDFPage.REDACT_IMAGE_UNLESS_INVISIBLE3仅在图片可见部分侵入涂黑区域时整张移除源码注释提示该方式在去标识化阶段可能泄漏不可见信息需谨慎使用PDFPage.REDACT_LINE_ART_NONE0不处理线条图形line artPDFPage.REDACT_LINE_ART_REMOVE_IF_COVERED1线条被涂黑区域覆盖时移除PDFPage.REDACT_LINE_ART_REMOVE_IF_TOUCHED2线条只要与涂黑区域相交即移除PDFPage.REDACT_TEXT_REMOVE0移除与涂黑区域相交的文字默认安全行为PDFPage.REDACT_TEXT_NONE1不移除任何文字——源码明确警告这样做是不安全的此外 C 枚举中还定义了PDF_REDACT_TEXT_REMOVE_INVISIBLE移除重叠区域中的不可见文字层常用于清理 OCR 残留层但 JS 文档当前只列出上述 9 个常量使用时以文档列出的为准。applyRedactions(blackBoxes, imageMethod, lineArtMethod, textMethod)方法签名与默认值参数类型说明默认值blackBoxesboolean是否在涂黑位置保留黑底框—imageMethodnumber图片处理方式REDACT_IMAGE_PIXELSlineArtMethodnumber线条处理方式REDACT_LINE_ART_REMOVE_IF_COVEREDtextMethodnumber文字处理方式REDACT_TEXT_REMOVERedaction 是一种特殊批注用于永久删除PDF 内容。整个流程是不可逆的两步操作先创建Redaction批注圈定范围再调用applyRedactions真正执行删除var annot1 page.createAnnotation(Redaction) annot1.setRect([0, 0, 500, 100]) var annot2 page.createAnnotation(Redaction) annot2.setRect([0, 600, 500, 700]) page.applyRedactions(true, mupdf.PDFPage.REDACT_IMAGE_NONE)上例中只显式传了两个参数其余按默认值生效。FFI 实现source/tools/murun.c构造pdf_redact_options结构体定义见 include/mupdf/pdf/page.h对未定义的参数保留 C 侧默认值{ 1, PDF_REDACT_IMAGE_PIXELS, 0, 0 }最终调用pdf_redact_page执行全页去标识化。由于applyRedactions会重写页面内容流与资源执行后应保存文档PDFDocument.save/Document.saveIncremental并重新加载验证原始内容无法从文件中恢复。七、坐标体系与内容流处理getTransform()返回从 MuPDF 页面空间到 PDF 用户空间的变换。两种坐标系的关键区别可对照 coordinate-system.md 深入理解MuPDF 页面空间原点位于页面左上角y 轴向下增长单位固定为 72 dpi 下的点PDF 用户空间原点位置任意由页面盒子决定y 轴向上增长单位受UserUnit影响。var transform pdfPage.getTransform()需要说明的一点参考文档中该方法的返回类型标注为Rect但从源码看source/tools/murun.c实现是调用pdf_page_transform得到fz_matrix后通过ffi_pushmatrix压栈实际返回的是一个Matrix对象。在编写坐标换算逻辑时请以矩阵形式处理为准。process(processor)|only_mutool|标注表示该方法仅在mutool run环境可用。它遍历页面内容流contents stream把遇到的每个操作符回调给传入的PDFProcessor对象可用于审计、转换或统计页面绘制指令pdfPage.process(processor)从实现看source/tools/murun.cFFI 层先取pdf_page_resources与pdf_page_contents再用pdf_process_contents驱动 C 层解释器逐条执行页面指令PDFProcessor的回调对象new_js_processor创建的包装在每个操作符上被调用。PDFProcessor接口见 PDFProcessor.rst。八、仅 mutool 可用的其他页面能力以下三个方法在参考文档中带有|only_mutool|标记表示只在mutool run的完整 JS 环境里注册可用createSignature(name)创建一个以name作为字段标签field label的新签名控件返回PDFWidget。底层调用pdf_create_signature_widgetsource/tools/murun.cvar signatureWidget pdfPage.createSignature(test)countAssociatedFiles() / associatedFile(n)用于处理 PDF 的 Associated Files关联文件常见于 Office 导出的文档中嵌入的原始部件。注意文档特别强调countAssociatedFiles()返回的是本页关联的文件数而不是整份文档的总数文档级计数请使用PDFDocument.countAssociatedFiles参见 PDFDocument.rst。var count pdfPage.countAssociatedFiles() var obj pdfPage.associatedFile(0) // 0 n count越界返回 null实现分别对应 C 层的pdf_count_page_associated_files与pdf_page_associated_filesource/tools/murun.c后者返回表示第n个关联文件的 file specification 对象越界时返回null。clip(rect)把页面裁剪到给定矩形。注意clip是永久性的页面编辑不是渲染时的一次性裁剪执行后需要保存文档才能持久生效pdfPage.clip([0, 0, 200, 300])实现调用 C 层pdf_clip_pagesource/tools/murun.c。九、方法速查表与源码对照下表汇总 PDFPage.rst 定义的全部实例方法及其实现在murun.c中的位置方便按图索骥方法作用FFI 实现位置getObject()取底层PDFObjectmurun.c#L9630getAnnotations()全部批注数组murun.c#L9663getWidgets()全部表单控件数组murun.c#L9637setPageBox(box, rect)修改页面盒子murun.c#L9813createAnnotation(type)创建空白批注murun.c#L9689deleteAnnotation(annot)删除批注murun.c#L9704update()更新全部批注返回是否变化murun.c#L9730toPixmap(matrix, cs, alpha, extra, usage, box)渲染页面为Pixmapmurun.c#L9775applyRedactions(...)执行去标识化不可逆murun.c#L9742process(processor)遍历内容流回调PDFProcessormurun.c#L9757getTransform()页面空间到用户空间的变换murun.c#L9799createSignature(name)创建签名控件仅 mutoolmurun.c#L9715countAssociatedFiles()本页关联文件数仅 mutoolmurun.c#L9829associatedFile(n)取第 n 个关联文件对象仅 mutoolmurun.c#L9841clip(rect)永久裁剪页面仅 mutoolmurun.c#L9854十、实践建议与注意事项获取实例的唯一入口不要尝试new PDFPage()始终通过pdfDocument.loadPage(n)获取页码从 0 起算。修改后必须保存setPageBox、createAnnotation、deleteAnnotation、clip、applyRedactions修改的都是文档对象树中的状态执行Document.save或增量保存后变更才会落盘。Redaction 的不可逆性applyRedactions会真正从内容流中删除文字、改写图片与线条测试时应先在副本文件上执行若需要看起来涂黑但保留原文的效果请改用 Black 填充的批注而不是 Redaction。平台差异标注|only_mutool|的方法在mutool run中可用Redaction 常量文档标注为 MuPDF.js 专属在 Java/WASM 等其他绑定中对应的 API 面可能不同例如 Java 侧见 platform/java/src/com/artifex/mupdf/fitz/PDFPage.java。坐标系换算凡涉及批注矩形、裁剪矩形与页面像素的换算先用getTransform()拿到页面空间到用户空间的矩阵按Matrix处理再结合toPixmap的matrix参数统一坐标避免混用两种坐标系。赞分享图形学图像处理【免费下载链接】mupdfmupdf mirror项目地址https://gitcode.com/gh_mirrors/mu/mupdf点击查看免费下载相关推荐MuPDF JavaScript 绑定 PDFPage 详解PDF 页面的标注、批量编辑、永久涂黑与页面框操作MuPDF JavaScript 绑定 PDFPage 详解PDF 页面的标注、批量编辑、永久涂黑与页面框操作 本篇技术指南以本仓库内 MuPDF 子项目桌面应用文档MuPDF 的 DisplayListDevice 完整指南用 JavaScript 录制与重放页面渲染基于 SumatraPDF 内置 MuPDFMuPDF 的 DisplayListDevice 完整指南用 JavaScript 录制与重放页面渲染基于 SumatraPDF 内置 MuPDF Di桌面应用文档MuPDF JavaScript 绑定 ColorSpace 全解析颜色空间类型、ICC 配置文件与 Pixmap 渲染实战MuPDF JavaScript 绑定 ColorSpace 全解析颜色空间类型、ICC 配置文件与 Pixmap 渲染实战 导读 ColorSpace 是图形学图像处理创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考