工具说明
PDF 不是为逐字改写设计的格式:页面记录的是「在这个坐标用这个字体画这些字形」,没有段落回流的概念。所以这个工具提供两条不同的编辑路径——改写页面内容流里已有的文字,或者在页面之上叠加新的文字、签名、批注和遮盖块。前者结果仍是真正的文字,后者不受字体限制。
改原文时,工具用 pdf.js 抽出每段文字的原始字节和位置,再在页面内容流里定位对应的文字绘制操作符(Tj / TJ)并替换其中的字符串,最后由 pdf-lib 重新写出文件。叠加标注则写成 PDF 原生的注释对象(Ink / Square / FreeText / Stamp),是矢量的,放大不糊、体积很小,在其它阅读器里还能单独选中和删除。两者都在浏览器本地完成,文件不会上传服务器。
使用步骤
上传 PDF 并等待渲染
页面逐页渲染成底图,同时抽取文字块位置,页数越多耗时越长。
改原文:直接点页面上的文字
默认就是改原文模式,鼠标移到文字上会出现虚线框,点击输入新内容回车确认。页面随即用改写后的 PDF 重新渲染,字体和颜色就是导出后的样子。
加标注:文字 / 画笔 / 高亮 / 方框 / 图片
需要签名、手写批注或遮盖时用叠加工具,它们不受原字体限制。中文会按需下载字体并只嵌入用到的字形,导出后同样是真正的文字。
保存并下载
导出时先改写内容流里的原文,再把标注图层盖上;无法改写的原文会明确列出原因,不会悄悄写成空白。
支持范围与限制
- 改原文的实现
- 定位并替换页面内容流里的 Tj / TJ 字符串,沿用原有字体,不是盖图层
- 改原文的前提
- 文字在页面自己的内容流里、字体为单字节字体,且新文字每个字符在原字体中有字形
- 失败时的行为
- 编辑时立刻报出原因并跳过,绝不写出渲染成空白或豆腐块的 PDF
- 字距处理
- TJ 数组里的字距微调分段会被合并到第一段,新文字按字体自身宽度排布
- 叠加标注
- 写成原生注释对象:画笔 / 高亮 → Ink,方框 → Square,文字 → FreeText,图片 → Stamp
- 预览方式
- 改完立刻把改写写进 PDF 并重新渲染该页,预览与导出结果一致
- 标注清晰度
- 矢量输出,与分辨率无关;只有认不出的对象和缺字形的文字才会单独栅格化
- 旋转页面与裁切页
- 按 /Rotate 和 CropBox 换算坐标,横向扫描件、出血裁切稿上的标注都不会错位
- 处理位置
- 渲染、改写、标注和写回全部在浏览器本地完成,文件不上传
典型使用场景
修正正式文件里的数字或日期
合同金额、报价、生效日期写错时直接改原文,改完仍是可选中、可检索的文字,不留遮盖痕迹。
签署和回填表单
用画笔手写签名,或插入透明背景签名图片,再用文字工具补上日期和姓名。
评审意见直接写在稿件上
用高亮标出有问题的段落,旁边写一段说明,对方打开就知道批注指向哪里。
遮盖来不及重做的内容
原字体无法改写时,用填充方框盖住旧内容,再在上面写正确文字。
使用前需要知道的事
- 改原文不会重排段落:起点坐标不变,新文字变长不会挤开后面的内容,也不会自动换行。
- 三种情况无法改写原文,工具会在你编辑时就逐条说明:文字不在页面内容流里(例如在表单域或 Form XObject 中)、字体是多字节 CID 字体、原字体里没有新文字需要的字形(中文子集字体常见)。
- 填充方框只是盖住视觉内容,被盖住的文字仍在文字层里可被复制提取,不能当作脱敏涂黑使用;真正要删掉的文字请用改原文。
- 导出会重写文件,已有的数字签名会失效;加密 PDF 需要先解除密码再编辑。
相关概念
- 内容流(content stream)
- PDF 页面里记录绘制指令的部分。Tj 和 TJ 是其中的文字绘制操作符,改原文就是替换它们携带的字符串。
- 字体子集(subset)
- 生成 PDF 时只嵌入文档实际用到的字形。这让文件更小,但也意味着原字体里没有的字符无法直接写入。
- /Rotate
- 页面的显示旋转角度,取值 0/90/180/270。阅读器按它旋转页面,但页面坐标系不变,所以标注需要换算才能对齐。