如何将文本对象添加到现有的pdf中

2023-12-04

我有一个源 pdf,我正在通过添加文本对象来修改它。我正在使用 PDF 规范中提到的“增量更新”。但是,在使用此方法添加文本对象时,我犯了一些错误,导致 pdf 在 Adob​​e Reader 11 中无法正确呈现。当打开 pdf 并双击它时,添加的文本对象将被删除。我发现这是由于文本注释造成的。

现在我想知道如何使用增量更新添加新的文本对象?自由文本注释的内容和 RC 必须如何维护?

另外是否可以禁用或删除注释,以便可以轻松避免我的问题?因为我想要一个简单的 pdf,所以我不需要注释选项。

我正在使用的源pdf是here.

添加文本对象后修改后的pdf为here.

我不确定源 pdf 本身是否符合 pdf 规范。


首先,让我向您展示,如果您可以使用一个像样的 PDF 库,事情会变得多么容易。我使用 iTextSharp 作为示例,但也可以使用 PDFBox 或 PDFNet 等其他工具来完成(@Ika 在他的回答中已经提到过):

PdfReader reader = new PdfReader(sourcePdf);
using (PdfStamper stamper = new PdfStamper(reader, targetPdfStream)) {
  Font FONT = new Font(Font.FontFamily.HELVETICA, 12, Font.BOLD, new GrayColor(0.75f));
  PdfContentByte canvas = stamper.GetOverContent(1);
  ColumnText.ShowTextAligned(
    canvas,
    Element.ALIGN_LEFT, 
    new Phrase("Hello people!", FONT), 
    36, 540, 0
  );
}

(源自网络化 iTextSharp 示例 StampText.cs解释于第6章 of iText 实际应用 — 第二版.)

(您选择哪个 PDF 库取决于您的一般要求和可用的许可证模型。)

尽管此类 PDF 库易于使用,但如果您坚持手动执行此操作,请注意以下几点:

首先,您必须找到要添加内容的页面的页面字典。根据 PDF 的类型,这可能已经需要解压缩对象流等,但在您的示例中修改1.pdf那是没有必要的:

7 0 obj
  <</Rotate 90
    /Type /Page
    /TrimBox [ 9.54 6.12 585.68 835.88 ]
    /Resources 8 0 R
    /CropBox [ 0 0 595.22 842 ]
    /ArtBox [ 9.54 18.36 585.68 842 ]
    /Contents [ 9 0 R 10 0 R 11 0 R 12 0 R 13 0 R 14 0 R 15 0 R 16 0 R ]
    /Parent 6 0 R
    /MediaBox [ 0 0 595.22 842 ]
    /Annots 17 0 R
    /BleedBox [ 9.54 6.12 585.68 835.88 ]
  >>
endobj 

您会看到对内容流的引用数组。这是您必须添加新页面内容的地方。您可以操作现有流或创建新流并将其添加到该数组中。

(大多数 PDF 的内容流都是压缩的。因此,对于一般情况,您必须先解压缩流,然后才能对其进行处理。因此,在我看来,更简单的方法是启动一个新流。)

您选择操作最后引用的流 16 0,该流在 PDF 中未压缩:

16 0 obj
<</Length 37 0 R>>
stream
  S 1 0 0 1 13.183 0 cm 0 0 m
  [...]
  0 10 -10 -0 506.238 342.629 Tm
  .13333 .11765 .12157 scn
  -.0002 Tc
  .0006 Tw
  (the Bank and branch on which cheque is drawn\).)Tj

  /F1 2 Tf
  -15.1279 10.9462 Td
  (abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~!@#$%^&*aaaaaaaaaaaaa)Tj

  /F2 1 Tf
  015.1279 01.9462 Td
  (ANAabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789)Tj

  ET
endstream
endobj 

我猜想,您添加的内容是底部的两个 3 行,它们首先选择一种字体,然后定位插入点,最后打印一组字母。

现在你说你添加文本 abc..z 和 ABC...Z 只是为了测试。但字母 b j k q v 等没有出现在 pdf 中。第二次添加字母时,问题变得更加明显;这里只显示大写的“A”和“N”。

The added letter groups

这是因为相关字体被嵌入到 PDF 中 --- 字体被嵌入到 PDF 中,以允许没有相关字体的系统上的 PDF 查看器显示 PDF --- 但它们是未完全嵌入,仅嵌入该字体所需的字符子集。

让我们寻找仅出现“N”和“A”的字体 F2:

根据页面对象,可以在对象8 0中找到页面资源:

8 0 obj
  <</Font <</F1 45 0 R /TT2 46 0 R /F2 47 0 R>>
    /ExtGState <</GS2 48 0 R>>
    /ProcSet [ /PDF /Text ]
    /ColorSpace <</Cs6 49 0 R>>
  >>
endobj 

所以F2定义在47 0中:

47 0 obj
  <</Subtype /Type1
    /Type /Font
    /Widths [ 722 250 250 250 250 250 250 250 250 250 250 250 250 722 ]
    /Encoding 52 0 R
    /FirstChar 65
    /FontDescriptor 53 0 R
    /ToUnicode 54 0 R
    /BaseFont /ILBPOB+TimesNewRomanPSMT-Bold
    /LastChar 78
  >>
endobj 

在引用的 ToUnicode 映射 54 0 中,您会看到

54 0 obj
<</Length 55 0 R>>stream
  /CIDInit /ProcSet findresource begin 12 dict begin begincmap /CIDSystemInfo <<
  /Registry (AAAAAA+F2+0) /Ordering (T1UV) /Supplement 0 >> def
  /CMapName /AAAAAA+F2+0 def
  /CMapType 2 def
  1 begincodespacerange <41> <4e> endcodespacerange
  2 beginbfchar
  <41> <0041>
  <4e> <004E>
  endbfchar
  endcmap CMapName currentdict /CMap defineresource pop end end
endstream
endobj 

在此映射中,您会看到仅映射字符代码 0x41 'A' 和 0x4e 'N'

在您的文档中,该字体仅用于在金额表单元格中打印“NA”,而不用于其他用途。因此,仅嵌入这两个字母“N”和“A”,这会导致您使用该字体进行添加时仅输出这些字母。

因此,要成功向页面添加文本,您必须检查与页面关联的字体资源以获取它们提供的字形(并限制您对这些字形的添加),或者必须添加您自己的字体资源。

由于编码中字符的存在通常不像这里那么容易看到(ToUnicode 是可选的),我建议您添加自己的字体资源。 PDF 规范ISO 32000-1解释了如何做到这一点。

此外,您还声明了文本的 x 和 y 轴位置在 pdf 中无法正确显示。虽然您没有确切说明您的意思,但您应该知道,在内容流中,您可以对页面的坐标系应用仿射变换,即拉伸、倾斜、旋转和移动轴。

如果您想使用原始坐标系并且不依赖坐标来正确添加内容,则应该向包含以下内容的页面添加初始内容流:q运算符(至将当前图形状态保存到图形状态堆栈中)并在新的最终内容流中开始添加Q运算符(至通过从堆栈中删除最近保存的状态并将其设为当前状态来恢复图形状态).

EDIT作为示例,我将顶部 C# 代码的 Java 等效项应用到您的修改1.pdf激活追加模式。结果更改或添加了以下对象:

页面对象 7 0 已更新:

7 0 obj
  <</CropBox[0 0 595.22 842]
    /Parent 6 0 R
    /Contents[69 0 R 9 0 R 10 0 R 11 0 R 12 0 R 13 0 R 14 0 R 15 0 R 16 0 R 70 0 R]
    /Type/Page
    /Resources<<
      /ExtGState<</GS2 48 0 R>>
      /ProcSet [/PDF /Text /ImageB /ImageC /ImageI]
      /ColorSpace<</Cs6 49 0 R>>
      /Font<</F1 45 0 R/F2 47 0 R/TT2 46 0 R/Xi0 68 0 R>>
    >>
    /MediaBox[0 0 595.22 842]
    /TrimBox[9.54 6.12 585.68 835.88]
    /BleedBox[9.54 6.12 585.68 835.88]
    /Annots 17 0 R
    /ArtBox[9.54 18.36 585.68 842]
    /Rotate 90
  >>
endobj 

如果您与以前的版本进行比较,您会发现

  • 添加了两个新的内容流,开头为 69 0,结尾为 70 0;
  • 资源不再是间接对象,而是直接包含在此处;
  • 该资源包含位于 68 0 的新字体资源 Xi0。

现在让我们看看添加的对象。

这是 Helvetica-Bold 的字体资源,名为 Xi0,位于 68 0:

68 0 obj
  <</BaseFont/Helvetica-Bold
    /Type/Font
    /Encoding/WinAnsiEncoding
    /Subtype/Type1
  >>
endobj 

非嵌入的、标准的14种字体资源一点也不复杂……

现在有额外的内容流。 iText 确实压缩了它们,但我将在此处以未压缩状态显示它们:

69 0 obj
<</Length 1>>stream
  q
endstream
endobj
70 0 obj
<</Length 106>>stream 
  Q
  q
  0 1 -1 0 595.22 0 cm
  q
  BT
  1 0 0 1 36 540 Tm
  /Xi0 12 Tf
  0.75 g
  (Hello people!)Tj
  0 g
  ET
  Q
  Q
endstream
endobj 

因此,开头的新内容流存储当前图形状态,末尾的新内容流检索存储的状态,更改坐标系、文本插入位置,选择字体、字体大小和填充颜色,最后打印一个字符串。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何将文本对象添加到现有的pdf中 的相关文章

随机推荐

  • Select2-rails 无法与 ActiveAdmin 一起使用

    我在将 select2 rails 与 ActiveAdmin 集成时遇到困难 我按照设置步骤操作 Select2 rails Github 页面 https github com argerim select2 rails我添加了一行 r
  • c#编译的应用程序可以在未安装.net的机器上运行吗?

    我想为 Windows 开发一个小型实用程序 我更喜欢用 C 来做 因为它更容易 我是一名 Java 开发人员 该实用程序可供许多人下载 我假设其中一些人没有安装 net 框架 这个假设是否正确 假设我的目标是 win xp 及以上版本 我
  • 在Matlab中保存全局变量

    在 Matlab 中 当将变量声明为全局变量并使用 save 命令保存它时 在新会话中加载 mat 文件后 该变量也是全局变量 以下代码显示了此行为 一开始 我没有变量 gt gt who gt gt who global 然后 我创建全局
  • 更新间隔时间时警报管理器不工作

    阅读所有质量检查后 我没有得到任何正确的解决方案 我有 2 个问题1 即使我仅在清单中注册接收器 警报也会触发两次 不是通过代码 2 当我更新闹钟的间隔时间时 它会随机触发 这是我设置闹钟的方法 public void AlarmCall
  • 如何在java中扫描屏幕上的特定颜色/图像?

    我需要扫描屏幕上的特定图像 颜色 并返回该颜色出现位置的 x 和 y 坐标 我知道这可能包括使用 Robot 类截取屏幕截图 但不知道如何正确扫描该图像 如果您使用 Robot 类进行屏幕截图 您将获得 BuffereImage 类的对象
  • 使用 MIPS 的双重递归

    我正在尝试为该函数实现双重递归f n 2f n 1 3f n 2 1 我能够找出奇异递归并实现2f n 1 1它的一部分 但我不知道如何实现第二部分 这是我的奇异递归的工作代码 data prompt1 asciiz Enter the v
  • iPhone如何隐藏导航栏?

    目前我正在iPhone应用程序中工作 我有两个屏幕 如A和B A没有导航栏 但B有导航栏 所以我这样设置 Class A void viewDidLoad super viewDidLoad self title A self naviga
  • 将数据从部分视图提交到控制器 MVC

    我有一个就业记录列表 您还可以使用部分视图从同一页面添加就业记录 这里是雇佣 cshtml 它有一个记录列表的部分视图和一个用于添加出现在模式弹出窗口中的新记录的部分视图 h2 Employment Records h2 Html Rend
  • timedelta64 和日期时间转换

    我的数据框中有两个日期时间 时间戳 格式的列 df start df end 我想知道两个日期之间的持续时间 所以我创建了持续时间列 df duration df start df end 然而 现在duration列的格式为numpy t
  • Xcode 首选项 -> 帐户未保存

    一般在Xcode我们可以在偏好设置中保存不同的苹果帐户 它之前在之前的所有版本中都可以工作 上周我更新了Xcode并安装了Xcode version 10 0然后我添加了 3 4 个 Apple ID Xcode gt 首选项 gt 帐户
  • Swift:多个目标处理:宏不起作用[重复]

    这个问题在这里已经有答案了 从参考如何使用 swift 语言处理 XCode 中的多个目标 and https www appcoda com using xcode targets 我创建了三个目标 每个目标都有不同的包 ID 和应用程序
  • 如何将 Google Mock 与 CppUnitTestFramework 结合使用

    TL DR 您可以使用 GMock 向 Microsoft 本机 C 单元测试添加模拟功能 看我的答案请参阅下文了解详细信息 我想开始向我现有的一组本机单元测试添加模拟 这些测试是使用 Microsoft 编写的CppUnitTestFra
  • PHP pthread 中的对象变量丢失上下文

    我在 PHP 中使用 pthreads 并注意到 pthreads 在其上下文中丢失了对象变量 这是正常的还是错误 或者我做错了什么 class Downloader extends Thread private ch public fun
  • 嵌套函数或方法调用会降低应用程序的性能

    我正在使用 asp net 和 C 开发应用程序 其中我们的项目架构有很多嵌套函数调用 public Employe GetEmployeOrder orderid employe GetEmployeOrderWithDetails or
  • 在 Freemarker 模板中显示 Spring MVC 验证错误

    如果控制器返回绑定错误 我试图在我的 freemarker 模板中显示全局验证错误列表 我可以显示与字段关联的错误 但我想检测特定 bean 中何时发生错误并在页面顶部显示一条消息 我尝试使用下面的示例 但它不产生任何输出 lt sprin
  • Windows 和 Linux 之间的 C++ 可移植性

    我有一个关于编写可在 Windows 和 Linux 之间移植的程序的问题 最近我意识到 如果你编写一个使用任何类型的外部库的程序 如果该库没有 Linux 版本 或者在 Linux 中开发时没有 Windows 版本 那么你就完蛋了 那么
  • 如何使用 .htaccess url 重写添加 .php 扩展名?

    我已经在我的网站上设置了 htaccess 文件 该文件将 SLUG 文本显示为 URL 中的页面名称 但不带扩展名 例如真实网址是 www mywebsite com page php page about us 然后通过url重写加载到
  • 尝试使用 pygame.display.update 在 pygame 中显示 png 文件,它显示不到一秒然后消失。

    图像是一张扑克牌 我们使用的是 pygame 4 5 社区版和 pycharm 2 6 9 因为 2 7 不支持 pygame 这是学校 这是代码 import pygame pygame init picture pygame image
  • Pandas:如何通过以下方式连接数据帧?

    我想将多个数据帧连接成一个数据帧 我希望发生串联的方式如以下示例所示 Input tables A B C D 0 x p 2 4 1 y q 3 5 A B E F 0 x p 6 8 1 y q 9 10 Output table A
  • 如何将文本对象添加到现有的pdf中

    我有一个源 pdf 我正在通过添加文本对象来修改它 我正在使用 PDF 规范中提到的 增量更新 但是 在使用此方法添加文本对象时 我犯了一些错误 导致 pdf 在 Adob e Reader 11 中无法正确呈现 当打开 pdf 并双击它时