如何添加文本对象,以现有的PDF(How to add text object to existin

2019-07-20 18:33发布

我有我通过添加文本对象修改代码的PDF。 我使用的是在PDF说明书中提到的“增量更新”。 但是,虽然使用此方法添加文本对象,我做了一些错误,由于该PDF无法正常在Adobe Reader 11.当PDF被打开,但我双击渲染,所添加的文本对象被删除。 我想通了,这是由于文字注释。

现在我想知道怎样一个新的文本对象可以使用增量更新添加? 如何自由文本注释的内容和RC都必须要保持?

也可以禁用或删除注释,这样我的问题可以很容易地避免? 因为我想一个简单的PDF,我不想注解选项。

我使用的源PDF是在这里 。

添加文本对象后,修改PDF是在这里 。

我不知道该代码的PDF根据PDF规范本身是正确的。

Answer 1:

首先让我告诉你的事情多么容易的,如果你可以使用一个像样的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
  );
}

(从派生Web化iTextSharp的实施例 StampText.cs中说明第6章的iText的在行动-第二版 )。

(你选择哪一个PDF库,取决于您的总体要求和可用的许可证模式。)

如果,尽管放心使用这种PDF库的,你坚持做手工,这里的一番言论:

首先,你必须要找到你想要的内容添加到页面的页字典。 根据PDF的类型,这已经可能需要对象流等,但在你的样品减压modified1.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只是用于测试。 但信bjkqv等没有出现在PDF中。 这个问题变得更加明显你的第二个另外的信; 这里只是资本“A”和“N”的显示。

这是由于有问题的字体嵌入到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”嵌入,这导致在除了使用该字体只输出这些字母。

因此,为了成功地添加文本的页面,你要么必须检查与他们提供的字形的页面相关联的字体ressources(并限制你加入这些字形),或者你必须添加自己的字体资源。

由于在编码字符的存在往往是不容易看到,因为它是在这里(ToUnicode是可选的),我建议,您可以添加自己的字体ressources。 PDF规范ISO 32000-1解释了如何做到这一点。

此外,您声明文本的X和Y轴的位置没有正确显示PDF。 虽然你不说究竟是什么意思,你应该知道,在内容流中可以应用仿射变换页面的坐标系统,即拉伸,倾斜,旋转和移动轴。

如果你想使用原来的坐标系统,而不是依赖于坐标是在您添加适当的,你应该添加一个初始内容流至含有一Q运营商( 保存图形状态栈当前图形状态 )和页面启动添加剂在具有Q运营商新的最终内容流( 通过从栈中删除最近保存的状态,并使其成为当前状态恢复图形状态 )。

编辑作为一个样本,我申请了相当于Java,C#代码的顶部到您modified1.pdf与追加模式激活。 下面的对象被改变或添加的结果:

Page对象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新字体的ressource XI0。

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

这是黑体,粗体命名XI0字体的ressource在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 

因此,在开始时的新的内容流存储当前图形的状态,并在结束新的一个检索存储的状态,改变坐标系的位置的文字插入,选择字体,字体大小,和填充颜色,最后打印一个字符串。



文章来源: How to add text object to existing pdf