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

标签 c# itext7 redaction

更新:2021-01-15 - 添加赏金
我正在尝试更改编校注释以更改在您应用编校时刻录到 PDF 中的基础文本。在 Acrobat 中,您可以设置一组“编辑代码”,这些代码可用于确定您为什么将某些内容标记为已编辑。我的目标是用系统定义的值覆盖用户选择的内容。代码将在应用修订之前运行。
在我的尝试中,我发现将光标悬停在编辑框上时 Acrobat 产品中可用的“预览”是 Acrobat 独有的,大多数其他查看器不会显示预览。似乎预览与应用的实际编辑分开维护。我不需要更改预览中显示的文本,只需更改应用编辑后显示的内容。
我增加了 150 点声望的赏金,因为我认为我无法自己找出解决方案。我最初的问题指定了 iText7,因为这是我自己尝试中最接近的库。虽然我更喜欢使用 iText7,但我也会考虑使用我可以合理访问的其他库的解决方案(如果需要,我的预算很小,可以用来购买另一个库)。
我保留了我最初的问题以及我在下面亲自尝试过的后续问题。我感谢提供的任何帮助。
如果您需要 sample 进行测试,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-01-07 的调查结果
正如@mkl 的回答所指出的,PDF Redact Annotation Specification 阐明了底层的 redact annotation DOM 条目。 OverlayText 只是等式的一部分。如果您使用 OverlayText 那么一定有一个元素定义(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 修订注释的条目指定为

Key Type Value
OverlayText text string (Optional) A text string specifying the overlay text that should be drawn over the redacted region after the affected content has been removed. This entry is ignored if the RO entry is present.

(ISO 32000-2, Table 195 — Additional entries specific to a redaction annotation)


也许在您的源 PDF 中,修订注释有 RO 优先。
此外,该表说明了有关 的内容。大 入口:
Key Type Value
DA byte string (Required if OverlayText is present, ignored otherwise) The appearance string that shall be used in formatting the overlay text when it is drawn after the affected content has been removed (see 12.7.4.3, "Variable text"). This entry is ignored if the RO entry is present.

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

RO 同一个表中的条目指定为
Key Type Value
RO stream (Optional) A form XObject specifying the overlay appearance for this redaction annotation. After this redaction is applied and the affected content has been removed, the overlay appearance should be drawn such that its origin lines up with the lower-left corner of the annotation rectangle. This form XObject is not necessarily related to other annotation appearances, and may or may not be present in the AP dictionary. This entry takes precedence over the IC, OverlayText, DA, and Q entries.

那么现在该怎么办?
根据上面发布的详细信息,一个明显的选项是为更改的修订注释创建修订覆盖 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, 0, 0, 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,所以可能当前版本不接受上面生成的编辑外观,或者至少以不同的方式应用它。

关于c# - 如何更改在 Adob​​e Acrobat 中创建的密文注释的密文文本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65398905/

相关文章:

c# - ASP.NET MVC 4 跨字段或属性验证

c# - HttpClient 和 PushStreamContent

c# - 发送电子邮件验证链接以激活配置文件 c#

java - 我尝试使用 itext7 与 eclipse 生成 pdf 文件。但是当我在其上添加页面时,它将输出错误“java.lang.NullPointerException”

html - pdfHTML 不遵循 CSS 样式

javascript - 不使用输入标签的密码文本和切换

python - 使用 PIL 为高维图像绘制矩形时 draw.rectangle([x1, y1, x2, y2], fill ="Black") 出错

c# - 如何在 ssis c# 脚本任务中添加 Microsoft Office Interop

c# - iTextsharp 7 : Rotating a Stamp or Annotation