IT *_*her 3 pdf adobe pdf-generation annotations adobe-reader
我有一个源代码pdf,我通过添加文本对象进行修改.我正在使用PDF规范中提到的"增量更新".但是在使用这种方法添加文本对象时,由于pdf无法在Adobe Reader 11中正确呈现,我会犯一些错误.当打开pdf并双击它时,添加的文本对象将被删除.我发现这是由于文本注释.
现在我想知道如何使用增量更新添加新的文本对象?如何维护自由文本注释的内容和RC?
是否可以禁用或删除注释,以便轻松避免我的问题?因为我想要一个简单的pdf,我不想要注释选项.
我使用的源文件pdf就在这里.
添加文本对象后修改的pdf就在这里.
根据pdf规范,我不确定source 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
);
}
Run Code Online (Sandbox Code Playgroud)
(从派生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
Run Code Online (Sandbox Code Playgroud)
您会看到对内容流的引用数组.这是您必须添加新页面内容的位置.您可以操作现有流或创建新流并将其添加到该阵列.
(大多数PDF都会对其内容流进行压缩.因此,对于一般情况,您必须在对其进行处理之前对其进行解压缩.因此,在我看来,更简单的方法是启动新流.)
您选择操作PDF中未压缩的最后引用的流16 0:
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
Run Code Online (Sandbox Code Playgroud)
我收集的是你的新增内容,它们是底部的两个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
Run Code Online (Sandbox Code Playgroud)
所以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
Run Code Online (Sandbox Code Playgroud)
在参考的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
Run Code Online (Sandbox Code Playgroud)
在此映射中,您会看到只映射字符代码0x41'A'和0x4e'N'
在您的文档中,字体仅用于在数量表单元格中打印"NA",而不用于其他任何内容.因此,只嵌入了这两个字母'N'和'A',这导致您添加该字体只输出这些字母.
因此,要成功向页面添加文本,您必须检查与页面关联的字体资源以获取它们提供的字形(并限制您对这些字形的添加),或者您必须添加自己的字体资源.
由于编码中字符的存在通常不像在这里那样容易看到(ToUnicode是可选的),我建议你添加自己的字体资源.PDF规范ISO 32000-1解释了如何做到这一点.
此外,您声明文本的x和y轴位置未正确显示在pdf中.虽然您没有说明您的意思,但您应该知道,在内容流中,您可以将仿射变换应用于页面的坐标系,即拉伸,倾斜,旋转和移动轴.
如果要使用原始坐标系并且不依赖于添加的坐标,则应将初始内容流添加到包含q运算符的页面(以将当前图形状态保存在图形状态堆栈上)和开始你的补充与新的最终内容流Q运营商(以从栈中删除最近保存的状态,并使其成为当前状态恢复图形状态).
编辑作为一个示例,我将顶部的C#代码的Java等效项应用于您已修改的附加模式的modified1.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
Run Code Online (Sandbox Code Playgroud)
如果你与以前的版本进行比较,你就会看到
现在让我们看一下添加的对象.
这是Helvetica-Bold在68 0处命名为Xi0的字体资源:
68 0 obj
<</BaseFont/Helvetica-Bold
/Type/Font
/Encoding/WinAnsiEncoding
/Subtype/Type1
>>
endobj
Run Code Online (Sandbox Code Playgroud)
非嵌入式,标准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
Run Code Online (Sandbox Code Playgroud)
因此,开始时的新内容流存储当前图形状态,最后的新内容流检索存储状态,更改坐标系,文本插入位置,选择字体,字体大小和填充颜色,最后打印一个字符串.
| 归档时间: |
|
| 查看次数: |
3357 次 |
| 最近记录: |