gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 19:39:38 27 4
gpt4 key购买 nike

我有一个pdf源文件,正在通过添加文本对象进行修改。我正在使用PDF规范中提到的“增量更新”。但是,当使用这种方法添加文本对象时,由于在pdf在Adobe 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
);
}


(源自 Webified iTextSharp ExampleStampText.cs中解释的 chapter 6 iText in Action — 2nd Edition。)

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

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

首先,您必须找到要添加内容的页面的Page字典。根据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。但是字母b j k q v等未出现在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”,这导致您添加该字体时仅输出这些字母。

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

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

此外,您指出文本的x和y轴位置未正确显示为pdf。尽管您并未确切说明其含义,但应注意,在内容流中,您可以将仿射变换应用于页面的坐标系,即拉伸,倾斜,旋转和移动轴。

如果您想使用原始坐标系,而又不依赖于添加的坐标系,则应将初始内容流添加到包含aq运算符的页面上(以将当前图形状态保存在图形状态堆栈中)并开始使用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


如果与以前的版本进行比较,您会看到


添加了两个新的内容流,开始时为69 0,结束时为70 0;
资源不再是间接对象,而是直接包含在此处;
资源包含位于68 0的新Font资源Xi0。


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

这是Helvetica-Bold的字体资源,名称为Xi0 at 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


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

关于pdf - 如何将文本对象添加到现有的pdf,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15151097/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com