Chr*_*ide 5 c# redaction itext7
我正在尝试更改编校注释以更改在您应用编校时刻录到 PDF 中的基础文本。在 Acrobat 中,您可以设置一组“编辑代码”,这些代码可用于识别您为什么将某些内容标记为已编辑。我的目标是用系统定义的值覆盖用户选择的内容。代码将在应用修订之前运行。
在我的尝试中,我发现将光标悬停在编辑框上时 Acrobat 产品中可用的“预览”是 Acrobat 独有的,大多数其他查看器不会显示预览。似乎预览与应用的实际编辑分开维护。我不需要更改预览中显示的文本,只需更改应用编辑后显示的内容。
我增加了 150 点声望的赏金,因为我认为我自己无法找到解决方案。我最初的问题指定了 iText7,因为这是我自己尝试中最接近的库。虽然我更喜欢使用 iText7,但我也会考虑使用我可以合理访问的其他库的解决方案(如果需要,我的预算很小,可以用来购买另一个库)。
我保留了我最初的问题以及我在下面亲自尝试过的后续问题。我感谢提供的任何帮助。
如果您需要一个样本进行测试,此 DropBox文件夹中有一个名为的文件01 - Original.pdf,您可以将其用作源文档。期望的结果是能够将“原始覆盖文本”中的编辑应用到任何其他值(例如“新文本”)时出现的文本更改。
我正在尝试更改 PDF 中每个修订注释中包含的文本,使用iText7. 该PdfRedactAnnotation对象有一个被调用的方法SetOverlayText(),看起来它应该做我想做的事。所以,我写了一个方法来打开一个 PDF,遍历页面,然后遍历每个页面上的注释,并检查注释是否是PdfRedactAnnotation. 如果是,则调用SetOverlayText()。
在调试和查看注释属性时,我可以看到OverlayText确实发生了变化。但是,当我打开文件并通过将光标悬停在修订标记上来检查覆盖文本时,原始覆盖文本仍然存在。
此外,如果我应用了修订,原始覆盖文本将被刻录到页面中。
但是,当我右键单击注释(在应用编辑之前)时,覆盖文本会立即更新为新文本:
此时,当我应用修订时,新文本会被刻录到 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();
Run Code Online (Sandbox Code Playgroud)
正如@mkl 的回答所指出的,PDF Redact Annotation Specification 阐明了底层的 redact annotation DOM 条目。OverlayText只是等式的一部分。如果您使用OverlayText,则必须定义一个DA元素(DA 是一个为 OverlayText 提供格式信息的字符串)。最后,如果定义了RO,它将取代几乎所有其他独立显示条目。
我的测试文档是使用 Acrobat DC Pro 制作的,通过在 Acrobat 中手动添加编辑。这样做会产生一个包含所有上述条目的 Redact 注释。我的测试文档的副本可以在这个 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);
Run Code Online (Sandbox Code Playgroud)
(我通过检查相等比较器确认它们实际上是完全相同的引用。作为引用类型,它们true在使用 测试时都返回==)。
在进一步的测试中,我得出的结论是 RO 属性必须具有内部存储的相同 OverlayText 的副本。如果您有两个具有不同原始值的修订,您可以将 RO 元素从一个修订“复制”到另一个修订:
PdfObject ro = firstRedact.GetPdfObject().Get(PdfName.RO);
secondRedact.GetPdfObject().Put(PdfName.RO, ro);
Run Code Online (Sandbox Code Playgroud)
如果您这样做并应用修订,第一个修订中的“覆盖文本”将替换第二个修订中的“覆盖文本”。其他 RO 元素值也会被复制(例如 BBox,它定义了黑色矩形的尺寸)……但至少可以调整这些元素。
问题仍然是 RO 的 iText7 PdfObject 有 7 个子元素,并且它们或它们的后代元素似乎都没有暴露我试图更改的文本。
我的最后一个测试是我是否可以将 RO 元素从一个 PDF 复制到另一个(以便我可以使用带有注释的第二个源 PDF,其中已经配置了所需的 RO“覆盖文本”),但看起来间接对象不喜欢正在 .Put() 到其他文件中。
所以现在,我只能尝试找到一种方法来访问/更改存储在 RO 中的文本,或者从另一个文档中克隆预配置的 RO。
覆盖文本指定为
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
钥匙 类型 价值 覆盖文本 文本字符串 (可选)一个文本字符串,指定在删除受影响的内容后应在编辑区域上绘制的覆盖文本。如果RO条目存在,则忽略此条目。 (ISO 32000-2,表 195 \xe2\x80\x94 特定于密文注释的其他条目)
\n
也许在您的源 PDF 中,密文注释具有优先的RO。
\n此外,该表还提到了有关DA条目的内容:
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
钥匙 类型 价值 DA 字节串 (如果OverlayText存在,则为必需,否则忽略)在删除受影响的内容后绘制覆盖文本时,应在格式化覆盖文本时使用的外观字符串(请参阅 12.7.4.3,“变量文本”)。如果 RO 条目存在,则忽略此条目。
因此,如果您使用OverlayText,您还必须确保设置DA默认外观字符串。你是否?
\n同一个表中的RO条目指定为
\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
钥匙 类型 价值 反渗透 溪流 (可选)表单 XObject,指定此密文注释的覆盖外观。应用此修订并删除受影响的内容后,应绘制覆盖外观,使其原点与注释矩形的左下角对齐。这种形式的XObject不一定与其他注释外观相关,并且可能存在也可能不存在于AP词典中。该条目优先于IC、OverlayText、DA和Q条目。
根据上面发布的详细信息,一个明显的选择是为更改的密文注释创建密文覆盖 XObject ( RO )。您可以通过更换您的
\nif (annotation is PdfRedactAnnotation)\n{\n PdfRedactAnnotation redact = (PdfRedactAnnotation)annotation;\n redact.SetOverlayText(new PdfString("New Text"));\n}\nRun Code Online (Sandbox Code Playgroud)\n经过
\nif (annotation is PdfRedactAnnotation)\n{\n PdfRedactAnnotation redact = (PdfRedactAnnotation)annotation;\n redact.SetOverlayText(new PdfString("New Text"));\n Rectangle rectangle = redact.GetRectangle().ToRectangle();\n PdfStream stream = redact.GetRedactRolloverAppearance();\n if (stream != null)\n {\n rectangle = stream.GetAsArray(PdfName.BBox).ToRectangle();\n }\n PdfFormXObject redactionOverlay = new PdfFormXObject(rectangle);\n redactionOverlay.GetPdfObject().Put(PdfName.Matrix, new PdfArray(new double[] { 1, 0, 0, 1, -rectangle.GetX(), -rectangle.GetY() }));\n using (Canvas canvas = new Canvas(redactionOverlay, pdfDocument))\n {\n PdfCanvas pdfCanvas = canvas.GetPdfCanvas();\n pdfCanvas.SetFillColorGray(0);\n pdfCanvas.Rectangle(rectangle);\n pdfCanvas.Fill();\n pdfCanvas.SetFillColorGray(1);\n canvas.Add(new Paragraph("New Text"));\n }\n\n stream = redactionOverlay.GetPdfObject();\n redact.SetRolloverAppearance(stream);\n redact.SetDownAppearance(stream);\n redact.SetRedactRolloverAppearance(stream);\n}\nRun Code Online (Sandbox Code Playgroud)\n在Acrobat中编辑后的结果:
\n\n通过调整所使用的填充颜色和段落样式,您可以使外观更接近 Adobe Acrobat 生成的外观(或者您也可以生成完全属于您自己设计的外观)。
\n请注意,我只有一个相当旧的 Adobe Acrobat 版本 v9.5,因此当前版本可能不接受上面生成的密文外观,或者至少以不同的方式应用它。
\n