从 PDF 文件中的文本中删除下划线

Remove underlines from text in PDF file

我有一堆 link 损坏的 PDF 文件。 我需要删除那些 link,现在我可以执行以下操作:

  1. 删除 link 个操作
  2. 将文本颜色从蓝色更改为黑色

我不能做的是删除之前 link 文本下方的蓝色下划线。

我尝试了几个 .NET 的 PDF 库(因为这是我的主要平台)

欢迎您推荐任何编程语言、平台和库的解决方案。我只需要这样做。

在示例文档的情况下,下划线绘制为蓝色 (RGB 0,0,1) 填充的矢量图形矩形(细长的)。由于蓝色仅用于链接,我们可以使用该标准来找到有问题的矩形。

这里是一个使用 PDFBox 1.8.10 的示例实现:

void removeBlueRectangles(PDDocument document) throws IOException
{
    List<?> pages = document.getDocumentCatalog().getAllPages();
    for (int i = 0; i < pages.size(); i++)
    {
        PDPage page = (PDPage) pages.get(i);
        PDStream contents = page.getContents();

        PDFStreamParser parser = new PDFStreamParser(contents.getStream()); 
        parser.parse();
        List<Object> tokens = parser.getTokens();  

        Stack<Boolean> blueState = new Stack<Boolean>();
        blueState.push(false);

        for (int j = 0; j < tokens.size(); j++)  
        {  
            Object next = tokens.get(j);
            if (next instanceof PDFOperator)
            {
                PDFOperator op = (PDFOperator) next;  
                if (op.getOperation().equals("q"))
                {
                    blueState.push(blueState.peek());
                }
                else if (op.getOperation().equals("Q"))
                {
                    blueState.pop();
                }
                else if (op.getOperation().equals("rg"))
                {
                    if (j > 2)
                    {
                        Object r = tokens.get(j-3);
                        Object g = tokens.get(j-2);
                        Object b = tokens.get(j-1);
                        if (r instanceof COSNumber && g instanceof COSNumber && b instanceof COSNumber)
                        {
                            blueState.pop();
                            blueState.push((
                                    Math.abs(((COSNumber)r).floatValue() - 0) < 0.001 &&
                                    Math.abs(((COSNumber)g).floatValue() - 0) < 0.001 &&
                                    Math.abs(((COSNumber)b).floatValue() - 1) < 0.001));
                        }
                    }
                }
                else if (op.getOperation().equals("f"))
                {
                    if (blueState.peek() && j > 0)
                    {
                        Object re = tokens.get(j-1);
                        if (re instanceof PDFOperator && ((PDFOperator)re).getOperation().equals("re"))
                        {
                            tokens.set(j, PDFOperator.getOperator("n"));
                        }
                    }
                }
            }
        }

        PDStream updatedStream = new PDStream(document);  
        OutputStream out = updatedStream.createOutputStream();  
        ContentStreamWriter tokenWriter = new ContentStreamWriter(out);  
        tokenWriter.writeTokens(tokens);  
        page.setContents(updatedStream);
    }
}

(RemoveUnderlines.java)

original.pdf

将此应用于您的第一个示例文件original.pdf

public void testOriginal() throws IOException, COSVisitorException
{
    try (   InputStream resourceStream = getClass().getResourceAsStream("original.pdf")   )
    {
        PDDocument document = PDDocument.loadNonSeq(resourceStream, null);

        removeBlueRectangles(document);
        document.save("original-noBlueRectangles.pdf");

        document.close();
    }
}

(RemoveUnderlines.java)

结果

1178.pdf

您发表了评论

After testing this on many files I have to say this solution works incorrectly in some cases. For example in for this file (dropbox.com/s/23g54bvt781lb93/1178.pdf?dl=0) it removes the entire content of the page. Keep searching..

所以我将代码应用于您的新示例文件1178.pdf

public void test1178() throws IOException, COSVisitorException
{
    try (   InputStream resourceStream = getClass().getResourceAsStream("1178.pdf")   )
    {
        PDDocument document = PDDocument.loadNonSeq(resourceStream, null);

        removeBlueRectangles(document);
        document.save(new File(RESULT_FOLDER, "1178-noBlueRectangles.pdf"));

        document.close();
    }
}

(RemoveUnderlines.java)

这导致

所以我无法证实你所说的解决方案不正确;特别是我看到 它不会 删除页面的全部内容。

由于我无法重现您的观察结果,我假设您的设置中还有您尚未提及的其他问题。