图形学图像处理【免费下载链接】mupdfmupdf mirror项目地址https://gitcode.com/gh_mirrors/mu/mupdf点击查看免费下载本文以 MuPDF JavaScript 绑定中的StructuredTextWalker接口为核心完整讲解StructuredText.prototype.walk()提供的全部回调方法、每个回调的参数含义与触发条件并结合source/tools/murun.c中的 C 实现、include/mupdf/fitz/structured-text.h头文件与platform/wasm/lib/mupdf.ts中的实现说明回调背后对应的数据结构、选项开关如preserve-images、vectors、structured以及字符 flags 的位定义。读完本文你可以编写自定义的 walker 对象精确提取页面中每一个文本块、每一行、每个字符的坐标、字体、颜色与方向信息同时按选项收集图片、矢量图形与文档结构树。StructuredTextWalker 是什么一个StructuredTextWalker是一个带可选回调方法的对象用于迭代StructuredText对象的内容。官方参考文档见 StructuredTextWalker.rst其接口定义如下// |interface_type|这是一个接口类型的构造函数接口对象 class StructuredTextWalker { ... }在 JavaScript 绑定中你不需要“构造”一个 walker——只需要提供一个包含部分或全部回调方法的普通对象传给StructuredText.prototype.walk(walker)即可。MuPDF 在遍历时会逐个检查回调是否存在只调用你实际提供的方法因此 walker 的所有回调都是可选的。StructuredText对象本身不能直接构造需要通过Page.prototype.toStructuredText()获得详见 StructuredText 参考文档。该文档给出的最简遍历示例var sText page.toStructuredText() sText.walk({ beginLine: function (bbox, wmode, direction) { console.log(beginLine, bbox, wmode, direction) }, endLine: function () { console.log(endLine) }, beginTextBlock: function (bbox) { console.log(beginTextBlock, bbox) }, endTextBlock: function () { console.log(endTextBlock) }, beginStruct: function (standard, raw, index) { console.log(beginStruct, standard, raw, index) }, endStruct: function () { console.log(endStruct) }, onChar: function (utf, origin, font, size, quad, argb, flags) { console.log(onChar, utf, origin, font, size, quad, argb, flags) }, onImageBlock: function (bbox, transform, image) { console.log(onImageBlock, bbox, transform, image) }, onVector: function (bbox, flags, argb) { console.log(onVector, bbox, flags, argb) }, })全部回调方法逐一说明walk()按块block迭代StructuredText。对文本块会逐行遍历其行对每一行再逐字符遍历。每遇到一个块、行或字符就会触发对应的 walker 方法。完整回调清单如下回调方法参数触发时机beginTextBlock(bbox)Rect bboxStructuredText中每个文本块之前endTextBlock()无每个文本块之后beginLine(bbox, wmode, direction)Rect bbox、number wmode、Point direction文本块中每一行文字之前endLine()无每一行文字之后beginStruct(standard, raw, index)string standard、string raw、number index一个新的结构元素structure element开始时它未必与块/行严格嵌套endStruct()无每个结构元素之后onChar(c, origin, font, size, quad, color, flags)string c、Point origin、Font font、number size、Quad quad、Color color、number flags一行文字中的每一个字符onImageBlock(bbox, transform, image)Rect bbox、Matrix transform、Image imageStructuredText中的每个图片前提是提取选项设置了 preserve imagesonVector(bbox, flags, rgb)Rect bbox、Object flags、Array of number rgbStructuredText中的每个矢量图形前提是提取选项设置了 collect vectors下面对几个关键回调的参数展开说明。beginLine方向向量与 wmodebeginLine(bbox, wmode, direction)在块内每行文字开始前被调用bbox该行的边界框wmode书写模式0 表示水平书写1 表示垂直书写对应 C 头文件中fz_stext_line的wmode字段见 structured-text.hdirection基线的单位方向向量是归一化的Point。官方文档特别指出beginLine的direction参数是一个向量例如[0, 1]你可以对这个向量做三角运算来计算行的旋转角度。例如对水平文本direction约为[1, 0]角度为 0对向下书写的垂直文本约为[0, 1]角度为 90 度beginLine: function (bbox, wmode, direction) { // direction 是归一化基线方向(x, y) 对应角度弧度 var rotation Math.atan2(direction[1], direction[0]) var degrees rotation * 180 / Math.PI console.log(line direction:, direction, rotation:, degrees) }从 C 源码看direction直接来自fz_stext_line.dir字段头文件注释明确其为 “normalized direction of baseline”基线的归一化方向因此可以直接参与三角计算。onChar字符回调与 flags 位含义onChar对一行中的每个字符调用一次参数为c该字符UTF 编码的字符串通常是一个码点origin字符原点基线起点font该字符使用的Font对象size字号quad字符四边形用于精确定位可处理旋转/斜切color字符颜色sRGB 格式flags位标志组合含义由 C 层的fz_stext_char_flags枚举定义见 structured-text.h位值标志名含义1FZ_STEXT_STRIKEOUT删除线2FZ_STEXT_UNDERLINE下划线4FZ_STEXT_SYNTHETIC合成字形8FZ_STEXT_BOLD粗体真实或“伪”粗体16FZ_STEXT_FILLED填充绘制32FZ_STEXT_STROKED描边绘制64FZ_STEXT_CLIPPED被裁剪128FZ_STEXT_UNICODE_IS_CIDunicode 字段实际返回的是 CID256FZ_STEXT_UNICODE_IS_GIDunicode 字段实际返回的是 GID512FZ_STEXT_SYNTHETIC_LARGE大幅合成1024FZ_STEXT_HIGHLIGHT高亮这些样式类标志删除线、下划线、粗体等只有在提取时设置了collect-styles之类的选项后才会有意义。例如检测粗体字符onChar: function (c, origin, font, size, quad, color, flags) { if (flags 8) console.log(bold char:, c) if (flags 2) console.log(underlined char:, c) }需要注意的一点差异参考文档描述的签名是 7 个参数但从 murun.c 的实现mutool run使用的 JS 引擎绑定看onChar实际压入了 8 个参数——在flags之后还有一个bidi值奇数表示 RTL偶数表示 LTR而 wasm 绑定的 TypeScript 接口 中onChar的最后一个参数名就是bidi。编写回调时建议用函数剩余参数或只取前几个参数避免因绑定不同而多出一个尾参。同理murun.c中beginTextBlock还会附带一个块级flags对齐方式作为第二参数。onImageBlock需要 preserve images 选项onImageBlock(bbox, transform, image)对StructuredText中的每个图片调用前提是提取选项设置了 preserve images选项名preserve-images对应 C 层FZ_STEXT_PRESERVE_IMAGES见 structured-text.h。若没有设置该选项图片会被直接忽略回调永远不会触发。bbox图片在页面上的边界框transform图片变换矩阵imageImage对象可进一步读取像素数据。onVector需要 collect vectors 选项onVector(bbox, flags, rgb)对StructuredText中的每个矢量调用前提是提取选项设置了 collect vectors选项名vectors对应FZ_STEXT_COLLECT_VECTORS。参数bbox矢量图形的边界框flags形如{ isStroked: boolean, isRectangle: boolean }的对象rgb颜色数值数组。从 murun.c 的实现看flags 对象实际还会带上第三个字段continues表示该矢量是某条多段路径的一部分后续还有同一路径的段对应 C 层FZ_STEXT_VECTOR_CONTINUES完整的矢量标志枚举定义在 structured-text.h还包含isHighlight、isUnderline、isStrikeout等派生标志。beginStruct / endStruct结构树的深度优先遍历beginStruct(standard, raw, index)用于指示一个新的结构元素开始官方文档特别提醒它未必与文本块或行整齐嵌套May not be neatly nested within blocks or linesstandard标准结构类型名如Document、Section、Heading等来自 C 层fz_structure枚举经fz_structure_to_string转换raw文档自定义的非标准结构类型原始字符串index该节点在其所在层级的序号。这三个参数如何产生、为什么需要index在 C 头文件的长注释中有完整解释见 structured-text.hPDF 的结构树structure tree通过 MCID 标记内容归属文档内容在绘制顺序上可能与逻辑树顺序不一致。MuPDF 会把这棵树转换成begin_structure/end_structure的嵌套调用序列并且每次begin_structure都附带该节点在本层树中的index例如begin_structure(DOC, 0) begin_structure(STORY, 0) begin_structure(SECTION, 0) begin_structure(HEADING, 0)以及begin_structure(DOC, 0) begin_structure(STORY, 0) begin_structure(SECTION, 0) begin_structure(SUBSECTION, 1)有了index之后两处的SECTION/HEADING、SECTION/SUBSECTION的层级关系就变得无歧义了。MuPDF 会自动发送最小的一组end_structure/begin_structure配对来在树节点之间移动调用方只需按到达顺序处理即可。此外为了在结构化文本的数据结构里承载这种信息引入了新的STRUCT块类型使原本的线性块列表变成一棵树因此遍历结构信息需要按深度优先顺序进行。从murun.c的实现stext_walk可以印证遇到FZ_STEXT_BLOCK_STRUCT块时先调用beginStruct参数为standard字符串、raw字符串、index然后递归深入其first_block子列表最后调用endStruct()正好是深度优先遍历。walk() 的底层实现块类型分发JavaScript 绑定的walk()最终落到 C 层的块链表遍历上。以mutool run使用的实现 stext_walk() 为例它按块类型分发块类型C 枚举值分发动作文本块FZ_STEXT_BLOCK_TEXT调beginTextBlock逐行调beginLine/onChar/endLine最后endTextBlock图片块FZ_STEXT_BLOCK_IMAGE若 walker 提供onImageBlock则调用结构块FZ_STEXT_BLOCK_STRUCT若有down子结构beginStruct→ 递归子块 →endStruct矢量块FZ_STEXT_BLOCK_VECTOR若 walker 提供onVector则调用网格块FZ_STEXT_BLOCK_GRID当前 JS 回调中无对应方法块类型的完整枚举TEXT0、IMAGE1、STRUCT2、VECTOR3、GRID4见 structured-text.h。wasm 绑定的 TypeScript 实现 同样是这套逻辑先取first_block循环内根据block_type分发最后跟随block-next前进——也就是说对非结构页面walk 的顺序就是页面上块链表的线性顺序一旦设置了结构选项结构块会携带树形子链遍历自然转为深度优先。Java 平台也有等价的接口定义可作交叉参考StructuredTextWalker.java其中onChar明确带出flags与bidi两个尾参beginTextBlock带出块级flags与murun.c的 JS 实现一致。选项开关哪些数据能被收集到walker 的哪些回调会触发取决于toStructuredText()时传入的选项字符串。选项语法逗号分隔键值对、URL query 或 JSON 三种等价形式见 option-strings.md结构化文本选项全集见 stext-options.md。与 walker 直接相关的核心选项选项对应 C 标志对 walker 的影响preserve-imagesFZ_STEXT_PRESERVE_IMAGES打开后才有onImageBlock回调vectorsFZ_STEXT_COLLECT_VECTORS打开后才有onVector回调structuredFZ_STEXT_COLLECT_STRUCTURE打开后才有beginStruct/endStruct回调块列表变为树形preserve-spansFZ_STEXT_PRESERVE_SPANS同一行不合并 spanasJSON()需要它preserve-whitespaceFZ_STEXT_PRESERVE_WHITESPACE空白按原始形式保留preserve-ligaturesFZ_STEXT_PRESERVE_LIGATURES连字不展开为单个字符inhibit-spacesFZ_STEXT_INHIBIT_SPACES不在字符大间隙处补空格dehyphenateFZ_STEXT_DEHYPHENATE行尾连字符按软连字处理ignore-actualtextFZ_STEXT_IGNORE_ACTUALTEXT不应用 ActualText 替换clip/clip-rectFZ_STEXT_CLIP/FZ_STEXT_CLIP_RECT排除被完全裁剪的内容或限定收集区域lazy-vectors/fuzzy-vectorsFZ_STEXT_LAZY_VECTORS/FZ_STEXT_FUZZY_VECTORS控制矢量收集的行为延迟合并、模糊合并同色矩形各选项的完整注释含accurate-bboxes、collect-styles、segment、table-hunt等见 structured-text.h。一个典型的“全量收集”用法var sText page.toStructuredText(preserve-images,vectors,structured,preserve-spans) sText.walk({ beginTextBlock: function (bbox) { console.log(text block at, bbox) }, beginLine: function (bbox, wmode, direction) { console.log(line, wmode:, wmode, dir:, direction) }, onChar: function (c, origin, font, size, quad, color, flags) { // flags 8 为粗体flags 2 为下划线 if (flags 8) console.log(bold:, c) }, beginStruct: function (standard, raw, index) { console.log(enter struct:, standard, raw, index) }, endStruct: function () { console.log(exit struct) }, onImageBlock: function (bbox, transform, image) { console.log(image block at, bbox) }, onVector: function (bbox, flags, rgb) { console.log(vector, bbox, JSON.stringify(flags), rgb) } })实战要点与注意事项回调全部可选实现层在每次分发前都会检查回调是否存在如 murun.c 中的js_hasproperty判断只提供你关心的方法即可不需要的分支不会带来调用开销。触发条件由选项决定忘记preserve-images就没有onImageBlock忘记vectors就没有onVector忘记structured就没有beginStruct/endStruct。这与文档描述一致——这两个/三组回调默认不会触发。结构回调不与块/行整齐嵌套结构信息是树文本块是线性列表两者交织。walker 的到达顺序是深度优先的若要重建结构层级必须同时利用index参数与begin/end配对自行维护栈。行方向可用三角函数求角度direction是归一化向量Math.atan2(direction[1], direction[0])即可得到基线角度用于识别旋转文本、竖排文本wmode1等。字符级信息足够精细onChar提供 origin、quad、font、size、color 与 flags足以实现逐字符高亮、复制选区或按样式重建富文本quad是处理旋转字符定位的关键参数。不同绑定的参数小差异murun.cJS 引擎绑定的onChar会多传一个bidi参数beginTextBlock会多传一个块级 flagswasm 接口的onChar尾参名为bidi而省略了flags。跨绑定编写 walker 时建议以实际收到的参数为准做防御性处理。与 walk 互补的便捷方法StructuredText还提供asText()、asHTML(id)、asJSON(scale)、search(needle)、highlight(p, q)、copy(p, q)等方法见 StructuredText.rst。当你只需要纯文本、JSON 或搜索结果时可以不用手写 walker当需要自定义遍历逻辑如统计字体使用、按结构树分组导出时walk()才是正确的工具。同类回调模式的其他示例仓库中的 trace-device.js 演示了同一种“回调对象”编程风格用mutool run运行将每个绘图/文本操作打印出来与 walker 的写法一脉相承可作为理解 MuPDF 回调式 API 的入门示例。小结StructuredTextWalker是 MuPDF JavaScript 绑定中把StructuredText的块/行/字符三级数据完整“摊开”给应用层的接口文本块、行与字符走beginTextBlock→beginLine→onChar→endLine→endTextBlock的严格嵌套调用图片与矢量分别由选项控制的onImageBlock、onVector回调交付文档结构树则通过带index的beginStruct/endStruct以深度优先顺序呈现且允许与块/行不完全嵌套。结合 stext-options.md 中列出的选项、structured-text.h 中的结构定义与 murun.c 的分发实现你可以准确判断每个回调的触发时机与参数语义编写出可靠的页面内容遍历逻辑。赞分享图形学图像处理【免费下载链接】mupdfmupdf mirror项目地址https://gitcode.com/gh_mirrors/mu/mupdf点击查看免费下载相关推荐MuPDF 结构化文本遍历StructuredTextWalker 回调协议深度解析MuPDF 结构化文本遍历StructuredTextWalker 回调协议深度解析 StructuredTextWalker 是 MuPDF JavaScr桌面应用文档MuPDF JavaScript 绑定 PathWalker 接口详解用回调遍历路径绘制指令MuPDF JavaScript 绑定 PathWalker 接口详解用回调遍历路径绘制指令 PathWalker 是 MuPDF JavaScript 绑定图形学图像处理MuPDF JavaScript PathWalker 接口深度解析通过回调遍历 Path 矢量绘图指令MuPDF JavaScript PathWalker 接口深度解析通过回调遍历 Path 矢量绘图指令 PathWalker 是 MuPDF JavaScr桌面应用文档创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考