我有我通过添加文本对象修改代码的PDF。 我使用的是在PDF说明书中提到的“增量更新”。 但是,虽然使用此方法添加文本对象,我做了一些错误,由于该PDF无法正常在Adobe Reader 11.当PDF被打开,但我双击渲染,所添加的文本对象被删除。 我想通了,这是由于文字注释。
现在我想知道怎样一个新的文本对象可以使用增量更新添加? 如何自由文本注释的内容和RC都必须要保持?
也可以禁用或删除注释,这样我的问题可以很容易地避免? 因为我想一个简单的PDF,我不想注解选项。
我使用的源PDF是在这里 。
添加文本对象后,修改PDF是在这里 。
我不知道该代码的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
);
}
(从派生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
因此,在开始时的新的内容流存储当前图形的状态,并在结束新的一个检索存储的状态,改变坐标系的位置的文字插入,选择字体,字体大小,和填充颜色,最后打印一个字符串。