如何使用 PdfStamper 在 APPEND 模式下将图像添加到 pdf 文件?

How to add an image to a pdf file in APPEND mode using PdfStamper?

我正在使用 iTextSharp 库版本 5.5.6.0。 此文件包含可自定义的文本字段,并且有必要保留交互式文本表单字段:https://yadi.sk/i/yoUvDI9EmtVhc。 但我无法在 PdfTemplate 对象中添加图像。 现阶段c#中的代码为:

    string outpath = @"D:\pdf_\output.pdf";
    string inpath = @"D:\pdf_\input.pdf";
    string stamp = @"D:\pdf_\img.png";

This method does'nt add the image, but the text boxes are active.

            public static void onlyInteractive()
            {
                using (MemoryStream os = new MemoryStream())
                using (PdfReader pdfReader = new PdfReader(inpath))

//追加模式

                using (PdfStamper stamper = new PdfStamper(pdfReader, os, '[=12=]', true))
                {
                    iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(stamp);
                    image.SetAbsolutePosition(0, 0);

                    PdfTemplate template = PdfTemplate.CreateTemplate(stamper.Writer, image.Width, image.Height);
                    template.AddImage(image);

                    stamper.GetOverContent(1).AddTemplate(template, 150, 200, true); 

                    os.WriteTo(new FileStream(outpath, FileMode.Create, FileAccess.ReadWrite));
                }
            }

The behavior of this method back to the first.

            public static void onlyImage()
            {
                using (Stream output = new FileStream(outpath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
                using (PdfReader reader = new PdfReader(inpath))
                using (var stamper = new PdfStamper(reader, output, '[=13=]', true))
                {
                    iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(stamp);
                    image.SetAbsolutePosition(0, 0);

                    PdfTemplate template = PdfTemplate.CreateTemplate(stamper.Writer, image.Width, image.Height);
                    template.AddImage(image);

                    stamper.GetOverContent(1).AddTemplate(template, 150, 200, true); 
                }
            }

仅互动

此代码的问题是您在完成之前获取了输出 PDF:

using (PdfStamper stamper = new PdfStamper(pdfReader, os, '[=10=]', true))
{
    [...]
    os.WriteTo(new FileStream(outpath, FileMode.Create, FileAccess.ReadWrite));
}

stamper 关闭时(这里隐式地在其 using 块的末尾),一些尚未存储的 PDF 对象被写入,内部交叉引用和文件尾部被写入.

你先把os的内容写入文件。因此,您的结果文档不完整。 Adobe Reader 打开后会对其进行修复,这基本上就是您的原始文档。

仅图片

此代码本身是正确的,它将图像标记到文档上并正确存储。

你的问题是文档本身是 Reader-enabled,即它是用所谓的使用权签名[=72=签名的].此类签名会在打开文件时告诉 Adob​​e Reader 以提供显示编辑相关文档的其他功能。

但是当使用图像检查文档上的签名时,Adobe Reader 发现文档的更改方式与签名授予的使用权不兼容:图像已被更改添加到页面内容中,这是签名未授予的内容。因此,Adobe Reader 撤销了授予的功能,在您的情况下是表单编辑。

正在删除使用权签名

在这种情况下,一个选择是删除该签名。在这种情况下,不再通过该签名授予表单编辑权限。但是在较新的 Adob​​e Reader 版本中(如果我没记错的话,从第 XI 版开始)默认情况下所有文档都可以进行表单编辑!在您的情况下,由于签名无效,该功能已被删除!

这可以按如下方式完成:

using (Stream output = new FileStream(outpath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
using (PdfReader reader = new PdfReader(inpath))
using (var stamper = new PdfStamper(reader, output))
{
    reader.RemoveUsageRights();
    iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(stamp);
    image.SetAbsolutePosition(0, 0);

    PdfTemplate template = PdfTemplate.CreateTemplate(stamper.Writer, image.Width, image.Height);
    template.AddImage(image);

    stamper.GetOverContent(1).AddTemplate(template, 150, 200, true);
}

您现在可以在较新的 Adob​​e Readers 中编辑带图像的 PDF。

不幸的是,保存文档时出现错误。我不知道它们是否与源文档部分无效这一事实有关(Adobe Preflight 抱怨了很多问题,最重要的是使用了未定义的编码名称 Win1251Encoding)或者其他东西是否坏了。

正在删除追加模式下的使用权签名

附加模式下工作,我们必须手动删除使用权限签名。实际上,我们将从 Catalog:

中删除整个 Perms 字典
using (Stream output = new FileStream(outpath, FileMode.OpenOrCreate, FileAccess.Write, FileShare.None))
using (PdfReader reader = new PdfReader(inpath))
using (var stamper = new PdfStamper(reader, output, '[=12=]', true))
{
    reader.Catalog.Remove(PdfName.PERMS);
    stamper.MarkUsed(reader.Catalog);
    iTextSharp.text.Image image = iTextSharp.text.Image.GetInstance(stamp);
    image.SetAbsolutePosition(0, 0);

    PdfTemplate template = PdfTemplate.CreateTemplate(stamper.Writer, image.Width, image.Height);
    template.AddImage(image);

    stamper.GetOverContent(1).AddTemplate(template, 150, 200, true);
}

现在您可以编辑表格并保存文件(至少我可以在 Adob​​e Reader DC 中)。

PS: 正确坐标

OP 在评论中分享了另一个 PDF 并声明它

for the other file is impossible to place a picture on a page with landscape orientation.

OP 的代码确实有问题:

stamper.GetOverContent(1).AddTemplate(template, 150, 200, true); 

固定坐标150, 200是OP假设左下角为坐标系原点0, 0的标志。虽然情况经常如此,但这不一定是真的。人们总是必须考虑 CropBox(默认为 MediaBox),即对于 OP 的代码:

Rectangle cropBox = reader.GetCropBox(1);
stamper.GetOverContent(1).AddTemplate(template, cropBox.Left + 150, cropBox.Bottom + 200, true);

the library takes rotation not correctly, but gives 0 degrees.

但这是正确的!您的示例 PDF 有点特殊,因为它使用未旋转的矩形作为横向,使用旋转的矩形作为纵向。