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

时间:2016-01-11 11:51:14

标签: pdf pdfbox pdfsharp underline aspose

我有一堆链接断开的PDF文件。 我需要删除这些链接,现在我可以执行以下操作:

  1. 删除链接操作
  2. 将文字颜色从蓝色更改为黑色
  3. 我不能做的是删除之前链接的文本下面的蓝色下划线。

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

    • Aspost.PDF
    • PDFSharp
    • ceTe DynamicPDF
    • PDFBox的

    欢迎您在任何程序语言,平台和库中推荐解决方案。我只需要这样做。

1 个答案:

答案 0 :(得分:2)

在样本文档的情况下,下划线被绘制为蓝色(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

结果

original-noBlueRectangles.pdf page 1

1178.pdf

您发表了评论

  

在许多文件上测试后,我不得不说这个解决方案在某些情况下工作不正常。例如,对于此文件(dropbox.com/s/23g54bvt781lb93/1178.pdf?dl=0),它会删除页面的全部内容。继续搜索..

因此,我将代码应用于您的新示例文件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

导致

1178-noBlueRectangles.pdf page 1

因此,我无法确认您声称​​解决方案无法正常工作;特别是我看到它不会删除页面的整个内容。

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