使用PDFBOX基于PDF输出识别文本

 小荷蛋蛋图_945 发布于 2023-01-30 16:34

我使用PDF BOX获取PDF格式的文本颜色信息.我可以使用以下代码获取输出.但我怀疑StrokingColor代表什么,非抚摸颜色代表什么.基于此,我将如何决定哪个文本具有哪种颜色.有人建议我吗?我的cuurent输出是这样的:DeviceRGB DeviceCMYK java.awt.Color [r = 63,g = 240,b = 0] java.awt.Color [r = 35,g = 31,b = 32] 34.934998 31.11 31.875

PDDocument doc = null;
        try {
            doc = PDDocument.load(strFilepath);
            PDFStreamEngine engine = new PDFStreamEngine(ResourceLoader.loadProperties("org/apache/pdfbox/resources/PageDrawer.properties"));
            PDPage page = (PDPage)doc.getDocumentCatalog().getAllPages().get(1);
            engine.processStream(page, page.findResources(), page.getContents().getStream());
            PDGraphicsState graphicState = engine.getGraphicsState();
            System.out.println(graphicState.getStrokingColor().getColorSpace().getName());
            System.out.println(graphicState.getNonStrokingColor().getColorSpace().getName());
            System.out.println(graphicState.getNonStrokingColor().getJavaColor()); 
            System.out.println(graphicState.getStrokingColor().getJavaColor());
            float colorSpaceValues[] = graphicState.getStrokingColor().getColorSpaceValue();
            for (float c : colorSpaceValues) {
                System.out.println(c * 255);
            }
        }
        finally {
            if (doc != null) {
                doc.close();
            }
        }

mkl.. 5

根据OP希望的评论中的澄清

比较一个pdf页面的字体颜色与另一个pdf页面[...]如果有一个黑色的文本"Sample"和一些灰色的其他文本"sample1"....我需要知道样本 - >黑色,样本1 - >灰色这样......我想要全文及其颜色

PDFBox有一个文本提取引擎,PDFTextStripper.将它用于手头的任务有一些挑战,其中包括:

最初它不是为了在文本旁边提取颜色信息设计的; TextPosition它使用的对象甚至没有任何颜色属性.因此,我们将不得不对其进行一些扩展.

我们将首先注册颜色操作的监听器,以便跟踪颜色.

我们还会将TextPosition对象的颜色信息存储在另一个结构中(我宁愿相应地扩展文本位置,但由于几个难以访问的私有成员,这意味着相当麻烦).

这已经在这个答案中详细说明了; 对于背景,看那里.

PDF允许多种绘制文本的方式.字母可以用一种颜色填充,其边界可以用另一种颜色填充.它们的边界甚至可以作为后续绘图操作的剪切路径.我们只考虑填充和抚摸颜色.

绘制的文字可能稍后被其他图纸覆盖,或者完全隐藏它或改变其外观颜色.我们暂时忽略这一点.

如上所示,我们扩展PDFTextStripper如下:

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.pdfbox.util.PDFTextStripper;
import org.apache.pdfbox.util.TextPosition;

public class ColorTextStripper extends PDFTextStripper
{
    public ColorTextStripper() throws IOException
    {
        super();
        setSuppressDuplicateOverlappingText(false);

        registerOperatorProcessor("CS", new org.apache.pdfbox.util.operator.SetStrokingColorSpace());
        registerOperatorProcessor("cs", new org.apache.pdfbox.util.operator.SetNonStrokingColorSpace());
        registerOperatorProcessor("SC", new org.apache.pdfbox.util.operator.SetStrokingColor());
        registerOperatorProcessor("sc", new org.apache.pdfbox.util.operator.SetNonStrokingColor());
        registerOperatorProcessor("SCN", new org.apache.pdfbox.util.operator.SetStrokingColor());
        registerOperatorProcessor("scn", new org.apache.pdfbox.util.operator.SetNonStrokingColor());
        registerOperatorProcessor("G", new org.apache.pdfbox.util.operator.SetStrokingGrayColor());
        registerOperatorProcessor("g", new org.apache.pdfbox.util.operator.SetNonStrokingGrayColor());
        registerOperatorProcessor("RG", new org.apache.pdfbox.util.operator.SetStrokingRGBColor());
        registerOperatorProcessor("rg", new org.apache.pdfbox.util.operator.SetNonStrokingRGBColor());
        registerOperatorProcessor("K", new org.apache.pdfbox.util.operator.SetStrokingCMYKColor());
        registerOperatorProcessor("k", new org.apache.pdfbox.util.operator.SetNonStrokingCMYKColor());
    }

    @Override
    protected void processTextPosition(TextPosition text)
    {
        renderingMode.put(text, getGraphicsState().getTextState().getRenderingMode());
        strokingColor.put(text, getGraphicsState().getStrokingColor().getColorSpaceValue());
        nonStrokingColor.put(text, getGraphicsState().getNonStrokingColor().getColorSpaceValue());

        super.processTextPosition(text);
    }

    Map renderingMode = new HashMap();
    Map strokingColor = new HashMap();
    Map nonStrokingColor = new HashMap();

    final static List FILLING_MODES = Arrays.asList(0, 2, 4, 6);
    final static List STROKING_MODES = Arrays.asList(1, 2, 5, 6);
    final static List CLIPPING_MODES = Arrays.asList(4, 5, 6, 7);

    @Override
    protected void writeString(String text, List textPositions) throws IOException
    {
        for (TextPosition textPosition: textPositions)
        {
            Integer charRenderingMode = renderingMode.get(textPosition);
            float[] charStrokingColor = strokingColor.get(textPosition);
            float[] charNonStrokingColor = nonStrokingColor.get(textPosition);

            StringBuilder textBuilder = new StringBuilder();
            textBuilder.append(textPosition.getCharacter())
                       .append("{");

            if (FILLING_MODES.contains(charRenderingMode))
            {
                textBuilder.append("FILL:")
                           .append(toString(charNonStrokingColor))
                           .append(';');
            }

            if (STROKING_MODES.contains(charRenderingMode))
            {
                textBuilder.append("STROKE:")
                           .append(toString(charStrokingColor))
                           .append(';');
            }

            if (CLIPPING_MODES.contains(charRenderingMode))
            {
                textBuilder.append("CLIP;");
            }

            textBuilder.append("}");
            writeString(textBuilder.toString());
        }
    }

    String toString(float[] values)
    {
        if (values == null)
            return "null";
        StringBuilder builder = new StringBuilder();
        switch(values.length)
        {
        case 1:
            builder.append("GRAY"); break;
        case 3:
            builder.append("RGB"); break;
        case 4:
            builder.append("CMYK"); break;
        default:
            builder.append("UNKNOWN");
        }
        for (float f: values)
        {
            builder.append(' ')
                   .append(f);
        }

        return builder.toString();
    }
}

你可以这样称呼它:

PDFTextStripper stripper = new ColorTextStripper();

PDDocument document = PDDocument.load(SOURCE_FILE);

String text = stripper.getText(document);

生成的文本包含以下内容:

P{FILL:RGB 0.803 0.076 0.086;}e{FILL:RGB 0.803 0.076 0.086;}l{FILL:RGB 0.803 0.076 0.086;}l{FILL:RGB 0.803 0.076 0.086;}e{FILL:RGB 0.803 0.076 0.086;}

G{FILL:RGB 0.102 0.101 0.095;}r{FILL:RGB 0.102 0.101 0.095;}a{FILL:RGB 0.102 0.101 0.095;}z{FILL:RGB 0.102 0.101 0.095;}i{FILL:RGB 0.102 0.101 0.095;}e{FILL:RGB 0.102 0.101 0.095;}

对于佩尔感恩教堂从这个

佩尔和格拉齐

要么

K{FILL:RGB 0.0 0.322 0.573;}E{FILL:RGB 0.0 0.322 0.573;}Y{FILL:RGB 0.0 0.322 0.573;}

C{FILL:GRAY 0.0;}o{FILL:GRAY 0.0;}m{FILL:GRAY 0.0;}b{FILL:GRAY 0.0;}i{FILL:GRAY 0.0;}n{FILL:GRAY 0.0;}e{FILL:GRAY 0.0;}d{FILL:GRAY 0.0;}

对于KEY和由此组合:

关键和组合

String您可以创建一些以结构化方式同时包含颜色和字符信息的类,而不是将所有信息序列化为结果.就像现在创建String结果一样writeString,您可以更改此方法以将此类的实例添加到其中的某个列表中.

要求

至少需要PDFBox版本1.8.4才能完成这项工作.我使用2.0.0-SNAPSHOT测试它,但1.8.4就足够了.另一方面,1.8.3有一个错误,有时会转发错误的TextPosition对象writeString,参见 PDFBOX-1804和早期版本根本不提供TextPosition集合writeString.

1 个回答
  • 根据OP希望的评论中的澄清

    比较一个pdf页面的字体颜色与另一个pdf页面[...]如果有一个黑色的文本"Sample"和一些灰色的其他文本"sample1"....我需要知道样本 - >黑色,样本1 - >灰色这样......我想要全文及其颜色

    PDFBox有一个文本提取引擎,PDFTextStripper.将它用于手头的任务有一些挑战,其中包括:

    最初它不是为了在文本旁边提取颜色信息设计的; TextPosition它使用的对象甚至没有任何颜色属性.因此,我们将不得不对其进行一些扩展.

    我们将首先注册颜色操作的监听器,以便跟踪颜色.

    我们还会将TextPosition对象的颜色信息存储在另一个结构中(我宁愿相应地扩展文本位置,但由于几个难以访问的私有成员,这意味着相当麻烦).

    这已经在这个答案中详细说明了; 对于背景,看那里.

    PDF允许多种绘制文本的方式.字母可以用一种颜色填充,其边界可以用另一种颜色填充.它们的边界甚至可以作为后续绘图操作的剪切路径.我们只考虑填充和抚摸颜色.

    绘制的文字可能稍后被其他图纸覆盖,或者完全隐藏它或改变其外观颜色.我们暂时忽略这一点.

    如上所示,我们扩展PDFTextStripper如下:

    import java.io.IOException;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import org.apache.pdfbox.util.PDFTextStripper;
    import org.apache.pdfbox.util.TextPosition;
    
    public class ColorTextStripper extends PDFTextStripper
    {
        public ColorTextStripper() throws IOException
        {
            super();
            setSuppressDuplicateOverlappingText(false);
    
            registerOperatorProcessor("CS", new org.apache.pdfbox.util.operator.SetStrokingColorSpace());
            registerOperatorProcessor("cs", new org.apache.pdfbox.util.operator.SetNonStrokingColorSpace());
            registerOperatorProcessor("SC", new org.apache.pdfbox.util.operator.SetStrokingColor());
            registerOperatorProcessor("sc", new org.apache.pdfbox.util.operator.SetNonStrokingColor());
            registerOperatorProcessor("SCN", new org.apache.pdfbox.util.operator.SetStrokingColor());
            registerOperatorProcessor("scn", new org.apache.pdfbox.util.operator.SetNonStrokingColor());
            registerOperatorProcessor("G", new org.apache.pdfbox.util.operator.SetStrokingGrayColor());
            registerOperatorProcessor("g", new org.apache.pdfbox.util.operator.SetNonStrokingGrayColor());
            registerOperatorProcessor("RG", new org.apache.pdfbox.util.operator.SetStrokingRGBColor());
            registerOperatorProcessor("rg", new org.apache.pdfbox.util.operator.SetNonStrokingRGBColor());
            registerOperatorProcessor("K", new org.apache.pdfbox.util.operator.SetStrokingCMYKColor());
            registerOperatorProcessor("k", new org.apache.pdfbox.util.operator.SetNonStrokingCMYKColor());
        }
    
        @Override
        protected void processTextPosition(TextPosition text)
        {
            renderingMode.put(text, getGraphicsState().getTextState().getRenderingMode());
            strokingColor.put(text, getGraphicsState().getStrokingColor().getColorSpaceValue());
            nonStrokingColor.put(text, getGraphicsState().getNonStrokingColor().getColorSpaceValue());
    
            super.processTextPosition(text);
        }
    
        Map<TextPosition, Integer> renderingMode = new HashMap<TextPosition, Integer>();
        Map<TextPosition, float[]> strokingColor = new HashMap<TextPosition, float[]>();
        Map<TextPosition, float[]> nonStrokingColor = new HashMap<TextPosition, float[]>();
    
        final static List<Integer> FILLING_MODES = Arrays.asList(0, 2, 4, 6);
        final static List<Integer> STROKING_MODES = Arrays.asList(1, 2, 5, 6);
        final static List<Integer> CLIPPING_MODES = Arrays.asList(4, 5, 6, 7);
    
        @Override
        protected void writeString(String text, List<TextPosition> textPositions) throws IOException
        {
            for (TextPosition textPosition: textPositions)
            {
                Integer charRenderingMode = renderingMode.get(textPosition);
                float[] charStrokingColor = strokingColor.get(textPosition);
                float[] charNonStrokingColor = nonStrokingColor.get(textPosition);
    
                StringBuilder textBuilder = new StringBuilder();
                textBuilder.append(textPosition.getCharacter())
                           .append("{");
    
                if (FILLING_MODES.contains(charRenderingMode))
                {
                    textBuilder.append("FILL:")
                               .append(toString(charNonStrokingColor))
                               .append(';');
                }
    
                if (STROKING_MODES.contains(charRenderingMode))
                {
                    textBuilder.append("STROKE:")
                               .append(toString(charStrokingColor))
                               .append(';');
                }
    
                if (CLIPPING_MODES.contains(charRenderingMode))
                {
                    textBuilder.append("CLIP;");
                }
    
                textBuilder.append("}");
                writeString(textBuilder.toString());
            }
        }
    
        String toString(float[] values)
        {
            if (values == null)
                return "null";
            StringBuilder builder = new StringBuilder();
            switch(values.length)
            {
            case 1:
                builder.append("GRAY"); break;
            case 3:
                builder.append("RGB"); break;
            case 4:
                builder.append("CMYK"); break;
            default:
                builder.append("UNKNOWN");
            }
            for (float f: values)
            {
                builder.append(' ')
                       .append(f);
            }
    
            return builder.toString();
        }
    }
    

    你可以这样称呼它:

    PDFTextStripper stripper = new ColorTextStripper();
    
    PDDocument document = PDDocument.load(SOURCE_FILE);
    
    String text = stripper.getText(document);
    

    生成的文本包含以下内容:

    P{FILL:RGB 0.803 0.076 0.086;}e{FILL:RGB 0.803 0.076 0.086;}l{FILL:RGB 0.803 0.076 0.086;}l{FILL:RGB 0.803 0.076 0.086;}e{FILL:RGB 0.803 0.076 0.086;}
    

    G{FILL:RGB 0.102 0.101 0.095;}r{FILL:RGB 0.102 0.101 0.095;}a{FILL:RGB 0.102 0.101 0.095;}z{FILL:RGB 0.102 0.101 0.095;}i{FILL:RGB 0.102 0.101 0.095;}e{FILL:RGB 0.102 0.101 0.095;}
    

    对于佩尔感恩教堂从这个

    佩尔和格拉齐

    要么

    K{FILL:RGB 0.0 0.322 0.573;}E{FILL:RGB 0.0 0.322 0.573;}Y{FILL:RGB 0.0 0.322 0.573;}
    

    C{FILL:GRAY 0.0;}o{FILL:GRAY 0.0;}m{FILL:GRAY 0.0;}b{FILL:GRAY 0.0;}i{FILL:GRAY 0.0;}n{FILL:GRAY 0.0;}e{FILL:GRAY 0.0;}d{FILL:GRAY 0.0;}
    

    对于KEY和由此组合:

    关键和组合

    String您可以创建一些以结构化方式同时包含颜色和字符信息的类,而不是将所有信息序列化为结果.就像现在创建String结果一样writeString,您可以更改此方法以将此类的实例添加到其中的某个列表中.

    要求

    至少需要PDFBox版本1.8.4才能完成这项工作.我使用2.0.0-SNAPSHOT测试它,但1.8.4就足够了.另一方面,1.8.3有一个错误,有时会转发错误的TextPosition对象writeString,参见 PDFBOX-1804和早期版本根本不提供TextPosition集合writeString.

    2023-01-30 16:36 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有