使用 iTextSharp 删除 pdf 中的突出显示区域

Remove highlighted area in pdf using iTextSharp

我使用以下问题答案中的代码突出显示了 pdf 中的单词:

现在我想知道如何使用 iTextSharp 删除那些突出显示的矩形。

private void RemovehighlightPDFAnnotation(string outputFile, string highLightFile, int pageno, string highLightedText)
{
    PdfReader reader = new PdfReader(outputFile);
    using (FileStream fs = new FileStream(highLightFile, FileMode.Create, FileAccess.Write, FileShare.None))
    {
        using (PdfStamper stamper = new PdfStamper(reader, fs))
        {                
            PdfDictionary pageDict = reader.GetPageN(pageno);                
            PdfArray annots = pageDict.GetAsArray(PdfName.ANNOTS);                
            if (annots != null)
            {
                for (int i = 0; i < annots.Size; ++i)                   
                {
                    PdfDictionary annotationDic = (PdfDictionary)PdfReader.GetPdfObject(annots[i]);
                    PdfName subType = (PdfName)annotationDic.Get(PdfName.SUBTYPE);                                               
                    if (subType.Equals(PdfName.HIGHLIGHT))
                    {
                        PdfString str  = annots.GetAsString(i);
                        if(str==highLightedText)
                        {
                                annots.Remove(i); 
                        }                          

                    }
                }                  

            }
        }
    }

它删除了所有注释,但我想删除特定注释。 假设我在第 1 页突出显示了 united statesPatent Application Publication,现在我想单独删除美国。我将通过文本美国

我参考了这个 answer。这样,要获取突出显示的文本,您需要获取存储在 Highlight 注释中的坐标(存储在 QuadPoints 数组中),并且您需要使用这些坐标来解析页面内容中存在于这些坐标处的文本。

获取高亮标注坐标

正如 OP 澄清的那样,他实际上想要

get the highlighted annotation coordinates

从该区域提取文本,检查它是否与相关短语匹配,并且(如果匹配)删除注释。

由于有问题的代码总是只用每个注释标记一个矩形,并选择矩形只包含有问题的文本,他可以简单地使用注释矩形

annotationDic.GetAsArray(PdfName.RECT)

在更一般的情况下(即对于从一行末尾开始到下一行开始结束的高亮注释),他需要检查四边形点

annotationDic.GetAsArray(PdfName.QUADPOINTS)

它描述了一组四边形。

例如如果示例来自 (突出显示 单词 "support" 在 OP 样本 PDF 的第三个文档页面 上的出现,方法

private void ReportHighlightPDFAnnotation(string highLightFile, int pageno)
{
    PdfReader reader = new PdfReader(highLightFile);
    PdfDictionary pageDict = reader.GetPageN(pageno);
    PdfArray annots = pageDict.GetAsArray(PdfName.ANNOTS);
    if (annots != null)
    {
        for (int i = 0; i < annots.Size; ++i)
        {
            PdfDictionary annotationDic = (PdfDictionary)PdfReader.GetPdfObject(annots[i]);
            PdfName subType = (PdfName)annotationDic.Get(PdfName.SUBTYPE);
            if (subType.Equals(PdfName.HIGHLIGHT))
            {
                Console.Write("HighLight at {0} with {1}\n", annotationDic.GetAsArray(PdfName.RECT), annotationDic.GetAsArray(PdfName.QUADPOINTS));
            }
        }
    }
}

报告

HighLight at [224.65, 654.03, 251.08, 662.03] with [221.65, 654.03, 251.08, 654.03, 221.65, 663.03, 251.08, 663.03]
HighLight at [80.9, 574.13, 107.28, 582.13] with [77.9, 574.13, 107.28, 574.13, 77.9, 583.13, 107.28, 583.13]
HighLight at [209.3, 544.33, 235.67, 552.33] with [206.3, 544.33, 235.67, 544.33, 206.3, 553.33, 235.67, 553.33]

特别是这些值 不是 null 正如 OP 在他的评论中声称的那样

null value only i get for PdfArray annots = pageDict.GetAsArray(PdfName.QUADPOINTS) and annotationDic.GetAsArray(PdfName.RECT)

另一种方法

如果我是 OP,我会将私人数据添加到我创建的注释中,其中包含突出显示的短语。当他想删除给定短语的注释时,他可以简单地检查该私有数据。

即使是从有限的区域提取文本也是一项成本非常高的操作,因为必须解析页面内容流和可能存在的大量表单 xobject 流。

循环设计警告

OP 想要删除此循环中的注释:

for (int i = 0; i < annots.Size; ++i)                   
{
    PdfDictionary annotationDic = (PdfDictionary)PdfReader.GetPdfObject(annots[i]);
    PdfName subType = (PdfName)annotationDic.Get(PdfName.SUBTYPE);                                               
    if (subType.Equals(PdfName.HIGHLIGHT))
    {
        PdfString str  = annots.GetAsString(i);
        annots.Remove(i);                           
    }
}                  

问题:如果他在索引 i 并删除此注释,则之前的 i+1st 注释变为 i个。不过,下一个要检查的注释是现在的 i+1st,以前的 i+1st 注释不会被检查或删除。