微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何更改在 Adob​​e Acrobat 中创建的密文注释的密文文本

如何解决如何更改在 Adob​​e Acrobat 中创建的密文注释的密文文本

更新:2021-01-15 - 添加赏金

我正在尝试更改密文注释,以更改在您应用密文时刻录到 PDF 中的基础文本。在 Acrobat 中,您可以设置一组“编辑代码”,这些代码可用于确定您为什么将某些内容标记为已编辑。我的目标是用系统定义的值覆盖用户选择的内容代码将在应用修改之前运行。

在我的尝试中,我发现将光标悬停在编辑框上时在 Acrobat 产品中可用的“预览”是 Acrobat 独有的,并且大多数其他查看器不会显示预览。似乎预览与应用的实际编辑分开维护。我不需要更改预览中显示的文本,只需更改应用编辑后显示内容

增加了 150 点声望的悬赏,因为我认为我无法独自找到解决方案。我最初的问题指定了 iText7,因为这是我自己尝试中最接近的库。虽然我更喜欢使用 iText7,但我也会考虑使用我可以合理访问的其他库的解决方案(如果需要,我的预算很小,可以用来购买另一个库)。

我保留了我最初的问题,并在下面进行了我个人尝试的后续工作。感谢您提供的任何帮助。

如果您需要一个样本进行测试,this DropBox 文件夹中有一个名为 01 - Original.pdf文件,您可以将其用作源文档。期望的结果是能够将在将“原始覆盖文本”中的编辑应用到任何其他值(例如“新文本”)时显示的文本进行更改。

原始问题:

我正在尝试使用 iText7 更改 PDF 中每个修订注释中包含的文本。 PdfRedactAnnotation 对象有一个名为 SetoverlayText()方法,看起来它应该按照我的意愿行事。因此,我编写了一个方法,可以打开 PDF,循环浏览页面,然后循环浏览每个页面上的注释,并检查注释是否为 PdfRedactAnnotation。如果是,则调用 SetoverlayText()

在调试和查看注释属性时,我可以看到 OverlayText 确实发生了变化。然而,当我打开文件并通过将光标悬停在修订标记上来检查覆盖文本时,原始覆盖文本仍然存在。

enter image description here

此外,如果我应用了编辑,原始覆盖文本会被刻录到页面中。

但是,当我右键单击注释(在应用编辑之前)时,覆盖文本会立即更新为新文本:

enter image description here

此时,当我应用编辑时,新文本会被刻录到 PDF 中。

有什么方法可以以编程方式触发编辑注释更新,而无需打开并右键单击每个注释?我在下面包含了我的代码。感谢您提供任何人可能提供的建议。

PdfDocument pdfDoc = new PdfDocument(new PdfReader(@"C:\temp\Test - Original.pdf"),new PdfWriter(@"C:\temp\Test - Output.pdf"));
Document doc = new Document(pdfDoc);
int pageCount = pdfDoc.GetNumberOfPages();
for (int i = 1; i <= pageCount; i++)
{
    var annotations = pdfDoc.GetPage(i).GetAnnotations();
    foreach(var annotation in annotations)
    {
        if (annotation is PdfRedactAnnotation)
        {
            PdfRedactAnnotation redact = (PdfRedactAnnotation)annotation;
            redact.SetoverlayText(new PdfString("New Text"));
        }
    }
}
doc.Close();

更新:截至 2021 年 1 月 7 日的调查结果

正如@mkl 的回答所指出的,PDF Redact Annotation Specification 阐明了底层的 redact annotation DOM 条目。 OverlayText 只是等式的一部分。如果您使用 OverlayText,则必须定义一个 DA 元素(DA 是一个字符串,为 OverlayText 提供格式信息)。最后,如果定义了 RO,它将取代几乎所有其他独立显示条目。

我的测试文档是使用 Acrobat DC Pro 制作的,通过在 Acrobat 中手动添加编辑。这样做会产生一个包含所有上述条目的 Redact 注释。我的测试文档的副本可以在 this DropBox 文件夹中找到。

(旁注:在我最初的问题中,我提到将鼠标悬停在修订的红色矩形上以预览应用的修订的外观......在多个浏览器和其他 PDF 查看器(如福昕阅读器)中进行测试后,似乎只有 Acrobat 产品才支持通过将鼠标悬停在红色轮廓上来“预览”编辑效果功能。所有其他测试的查看器只会显示红色边框,当您将鼠标悬停在将光标移到它上面。上面显示的黑色矩形只有在应用了屏蔽后才能在其他程序中查看。

其他测试表明,悬停预览与编校详细信息本身是分开维护的,Acrobat 会尝试使悬停详细信息与基础注释保持同步。测试时最好忽略悬停预览,修改后参考结果。

@mkl 建议删除 RO 条目以尝试让 OverlayText 优先是一个好主意,但不幸的是它没有奏效。与我的原始结果没有显着差异。

在 iText7 的 PdfRedactAnnotation 中摸索之后,我发现以下方法都会导致对 Redact 对象的 RO 条目的引用:

PdfRedactAnnotation redact = (PdfRedactAnnotation)annotation;
redact.GetRolloverAppearanceObject();
redact.GetRedactionRolloverAppearance();
redact.GetPdfObject().Get(PdfName.RO);
redact.GetAppearanceDictionary().Get(PdfName.R);

(我通过检查相等比较器确认它们实际上是完全相同的引用。作为引用类型,它们在使用 true 测试时都返回 ==)。

在进一步测试中,我得出结论,RO 属性必须具有内部存储的相同 OverlayText 的副本。如果您有两个具有不同原始值的修订,您可以将 RO 元素从一个修订“复制”到另一个修订:

PdfObject ro = firstRedact.GetPdfObject().Get(PdfName.RO);
secondRedact.GetPdfObject().Put(PdfName.RO,ro);

如果您这样做并应用修订,第一个修订中的“覆盖文本”将替换第二个修订中的“覆盖文本”。其他 RO 元素值也被复制(例如 BBox,它定义了黑色矩形的尺寸)...但至少可以调整这些元素。

问题仍然是 RO 的 iText7 PdfObject 有 7 个子元素,它们或其后代元素似乎都没有暴露我试图更改的文本。

我的最终测试是我是否可以将 RO 元素从一个 PDF 复制到另一个(以便我可以使用带有注释的第二个源 PDF,其中已经配置了所需的 RO“覆盖文本”),但它看起来像间接对象不喜欢被 .Put() 放到其他文档中。

所以现在,我只能尝试找到一种方法来访问/更改存储在 RO 中的文本,或者从另一个文档中克隆预配置的 RO。

解决方法

规范说明了什么?

密文注释的 OverlayText 条目指定为

类型 价值
OverlayText 文本字符串 (可选) 一个文本字符串,指定在删除受影响的内容后应在编辑区域上绘制的覆盖文本。如果存在 RO 条目,则忽略此条目。

(ISO 32000-2,表 195 — 特定于编校注释的附加条目)

也许在您的源 PDF 中,编辑注释具有 RO 优先。

此外,该表还说明了有关 DA 条目的内容:

类型 价值
DA 字节串 (如果 OverlayText 存在,则为必需,否则忽略) 在移除受影响的内容后绘制覆盖文本时,应用于格式化覆盖文本的外观字符串(见 12.7.4.3,“变量文本”)。如果存在 RO 条目,则忽略此条目。

如果您使用 OverlayText,因此,您还必须确保设置了 DA 默认外观字符串。是吗?


同表中的RO条目指定为

类型 价值
RO (可选) 一个表单 XObject,指定此编校注释的覆盖外观。应用此编辑并删除受影响的内容后,应绘制叠加外观,使其原点与注释矩形的左下角对齐。此表单 XObject 不一定与其他注释外观相关,并且可能会或可能不会出现在 AP 字典中。此条目优先于 ICOverlayTextDAQ 条目。

那现在该怎么办?

根据上面发布的详细信息,一个明显的选项是为更改的编校注释创建编校覆盖 XObject (RO)。您可以通过替换您的

if (annotation is PdfRedactAnnotation)
{
    PdfRedactAnnotation redact = (PdfRedactAnnotation)annotation;
    redact.SetOverlayText(new PdfString("New Text"));
}

if (annotation is PdfRedactAnnotation)
{
    PdfRedactAnnotation redact = (PdfRedactAnnotation)annotation;
    redact.SetOverlayText(new PdfString("New Text"));
    Rectangle rectangle = redact.GetRectangle().ToRectangle();
    PdfStream stream = redact.GetRedactRolloverAppearance();
    if (stream != null)
    {
        rectangle = stream.GetAsArray(PdfName.BBox).ToRectangle();
    }
    PdfFormXObject redactionOverlay = new PdfFormXObject(rectangle);
    redactionOverlay.GetPdfObject().Put(PdfName.Matrix,new PdfArray(new double[] { 1,1,-rectangle.GetX(),-rectangle.GetY() }));
    using (Canvas canvas = new Canvas(redactionOverlay,pdfDocument))
    {
        PdfCanvas pdfCanvas = canvas.GetPdfCanvas();
        pdfCanvas.SetFillColorGray(0);
        pdfCanvas.Rectangle(rectangle);
        pdfCanvas.Fill();
        pdfCanvas.SetFillColorGray(1);
        canvas.Add(new Paragraph("New Text"));
    }

    stream = redactionOverlay.GetPdfObject();
    redact.SetRolloverAppearance(stream);
    redact.SetDownAppearance(stream);
    redact.SetRedactRolloverAppearance(stream);
}

在 Acrobat 中编辑后的结果:

screenshot

通过调整使用的填充颜色段落样式,您可以使外观更接近于 Adob​​e Acrobat 生成的外观(或者您也可以完全生成外观您自己的设计)。

当心,我只有一个相当旧的 Adob​​e Acrobat 版本可用,v9.5,所以可能当前版本不接受上面或在至少以不同的方式应用它。

,

我能够更改编校注释覆盖文本,并在编校后使该文本正确显示在编校块上。我使用了 SyncFusion File Formats 中包含的 SyncFusion Essential PDF 库。 (我不隶属于 SyncFusion,但我确实通过我的雇主获得了他们的文件格式库的付费许可。)我使用 Adob​​e Acrobat Pro DC 进行了测试。

当我第一次尝试替换编校覆盖文本时,我遇到了与 SyncFusion 类似的问题,就像 OP 对 iText 7 所做的那样:在运行我的代码后,覆盖将显示为已更改,但编校会带回以前替换的覆盖文本。由于无法更改显示的文本覆盖和编辑过程可访问的覆盖文本,我通过编写进行所需更改的代码解决了这个问题,将 PDF 的注释导出到 JSON 文件,删除 PDF 的注释,然后将 JSON 文件重新导入 PDF。这会为文本覆盖和编校过程生成具有相同文本值的新注释(我相信,编校过程覆盖文本是由于创建 PDF 注释而生成的)。这是使用 SyncFusion Essential PDF 的代码:

using System.Drawing;
using Syncfusion.Pdf.Graphics;
using Syncfusion.Pdf.Interactive;
using Syncfusion.Pdf.Parsing;
using Syncfusion.Pdf;

PdfLoadedDocument loadedDocument = new PdfLoadedDocument(@"C:\Users\Joe\Desktop\Redact\MarkedOriginal.pdf");
PdfLoadedPage page = loadedDocument.Pages[0] as PdfLoadedPage;
foreach (PdfLoadedRedactionAnnotation redactionAnnotation in loadedDocument.Pages[0].Annotations)
{
    PdfStandardFont font = new PdfStandardFont(PdfFontFamily.Helvetica,10);
    redactionAnnotation.Font = font;
    redactionAnnotation.TextColor = Color.White;
    redactionAnnotation.BorderColor = Color.Black; //See note in SO answer about this
    redactionAnnotation.OverlayText = "New Text";
}

//Export,delete,and then import annotations to create a redaction annotation with the same preview and final redaction
loadedDocument.ExportAnnotations(@"C:\Users\Joe\Desktop\Redact\Output.json",AnnotationDataFormat.Json);

for (int i = 1; i <= loadedDocument.Pages[0].Annotations.Count; i++)
{
    loadedDocument.Pages[0].Annotations.RemoveAt(i);
}
loadedDocument.ImportAnnotations(@"C:\Users\Joe\Desktop\Redact\Output.json",AnnotationDataFormat.Json);
loadedDocument.Save();
loadedDocument.Close(true);

如果 OP 需要将密文标记框的边框设为黑色以外的颜色,则需要编写更多代码。我发现当我使用 redactionAnnotation.BorderColor = Color.Black; 时,密文标记框看起来像预期的那样。但是,当我使用 Color.Red 或其他颜色时,边框保留了黑色,新颜色也与第一个修订版接壤,只有黑色与 OP 提供的文件中的第二个修订版接壤。通过进一步研究,我怀疑这可以通过 SyncFusion、iText 7 或可能通过在将文件导入回 PDF 之前编辑 JSON 文件的注释 defaultappearance 行来修复。这是我运行代码时生成的 defaultappearance 行:

"defaultappearance": "1 1 1 RG 0 g 0 Tc 0 Tw 100 Tz 0 TL 0 Ts 0 Tr /Helv 10 Tf"

值得指出的是,SyncFusion 有免费和付费的软件许可层。根据 SyncFusion,SyncFusion Community License 对“年总收入低于 100 万美元且开发人员少于 5 名的公司和个人免费”。 SyncFusion File Formats Developer License 将涵盖其他所有人。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。