Java TextPosition边界框PDFBox

Java TextPosition边界框PDFBox,java,pdf,pdf-generation,pdfbox,Java,Pdf,Pdf Generation,Pdfbox,我正在尝试从TextPosition绘制相应的glyph边界框,如PDF 32000文档所示。 这是我的函数,它从字形空间到用户空间 @Override protected void processTextPosition(TextPosition text) { PDFont font = pos.getFont(); BoundingBox bbox = font.getBoundingBox(); Rectangle2D.Float rect

我正在尝试从TextPosition绘制相应的glyph边界框,如PDF 32000文档所示。

这是我的函数,它从字形空间用户空间

@Override 
protected void processTextPosition(TextPosition text) {
    PDFont font = pos.getFont();
    
    BoundingBox bbox = font.getBoundingBox();
    
    Rectangle2D.Float rect = new Rectangle2D.Float(bbox.getLowerLeftX(), bbox.getUpperRightY(), 
            bbox.getWidth(), bbox.getHeight());
    
    AffineTransform at = pos.getTextMatrix().createAffineTransform();
    
    if (font instanceof PDType3Font) {
        at.concatenate(font.getFontMatrix().createAffineTransform());
    } else {
        at.scale(1 / 1000f, 1 / 1000f);
    }
    Shape shape = at.createTransformedShape(rect);
    rectangles.add(fillBBox(text));
    
            
    super.processTextPosition(text);
}
下面是绘制提取矩形的函数:

private void drawBoundingBoxes() throws IOException {
    
    String fileNameOut = path.substring(0, path.lastIndexOf(".")) + "_OUT.pdf";
    log.info("Drawing Bounding Boxes for TextPositions");
    
    PDPageContentStream contentStream = new PDPageContentStream(document, 
            document.getPage(document.getNumberOfPages()-1),
            PDPageContentStream.AppendMode.APPEND, false , true );
    contentStream.setLineWidth(1f);
    contentStream.setStrokingColor(Color.RED);
    
    try{
        for (Shape p : rectangles) {
            p = all.get(0);
        double[] coords = new double[6];
        GeneralPath g = new GeneralPath(p.getBounds2D());
        for (PathIterator pi = g.getPathIterator(null);
             !pi.isDone();
             pi.next()) {
            System.out.println(Arrays.toString(coords));
            switch (pi.currentSegment(coords)) {
            case PathIterator.SEG_MOVETO:
                System.out.println("move to");
                contentStream.moveTo ((float)coords[0], (float) coords[1]);
                break;
                
            case PathIterator.SEG_LINETO:
                System.out.println("line to");
                contentStream.lineTo ((float)coords[0], (float) coords[1]);
                break;
                
            case PathIterator.SEG_CUBICTO:
                System.out.println("cubc to");
                contentStream.curveTo((float)coords[0], (float) coords[1],
                        (float)coords[2], (float) coords[3], 
                        (float)coords[4],(float) coords[5]);
                break;
                
            case PathIterator.SEG_CLOSE:
                System.out.println("close");
                contentStream.closeAndStroke();
                break;
            default:
                System.out.println("no shatt");
                break;
            }
            
        }
    
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        contentStream.close();
        document.save(new File(fileNameOut));
    }
}
然后,当我尝试在pdf上画图时,我得到以下第一个字母的结果(大写V)

我不知道我做错了什么。有什么想法吗?

D先生

我测试了你的代码,唯一需要做的修改就是反转Y轴。之所以需要这样做,是因为PDF用户空间的原点位于左下角,而Java 2D用户空间的原点位于左上角[1]

8.3.2.3用户空间

@Override 
protected void processTextPosition(TextPosition text) {
    PDFont font = pos.getFont();
    
    BoundingBox bbox = font.getBoundingBox();
    
    Rectangle2D.Float rect = new Rectangle2D.Float(bbox.getLowerLeftX(), bbox.getUpperRightY(), 
            bbox.getWidth(), bbox.getHeight());
    
    AffineTransform at = pos.getTextMatrix().createAffineTransform();
    
    if (font instanceof PDType3Font) {
        at.concatenate(font.getFontMatrix().createAffineTransform());
    } else {
        at.scale(1 / 1000f, 1 / 1000f);
    }
    Shape shape = at.createTransformedShape(rect);
    rectangles.add(fillBBox(text));
    
            
    super.processTextPosition(text);
}
用户空间坐标系应初始化为文档每页的默认状态。页面字典中的CropBox条目应指定与预期输出介质(显示窗口或打印页面)可见区域相对应的用户空间矩形。正x轴水平向右延伸,正y轴垂直向上延伸,如标准数学实践中所示(可通过页面字典中的旋转条目进行更改)。沿x轴和y轴的单位长度由页面字典中的UserUnit条目(PDF 1.6)设置(见表30)。如果该条目不存在或不受支持,则使用默认值1⁄72英寸。此坐标系称为默认用户空间。[2]

源代码 工具书类
  • 文件管理.便携式文件格式.第1部分:PDF 1.7,第8.3节:坐标系,第115页


  • 看看DrawPrintTextLocations示例,看看青色部分,其中一个有真实的边界框(大多数情况下)@tilmahauser我在边界框方面遇到了一些问题,在某些情况下会出现位移。我打印了为两个文件提取的边界框,如果你能看一下的话:我不知道为什么它发生在某些地方而不是其他地方。非常感谢这没什么帮助,这似乎是一个截图的PDF。目前尚不清楚这是来自一个PDF页面还是几个页面:在“Lavande”PDF中,右侧部分有位移,但左侧没有。我必须得到原始的PDF文件。如果这是来自几页,那么我怀疑它与cropbox有关。如果它来自一个PDF页面,那么我怀疑这是一个隐藏文本位置错误的文本图像。@TilmanHausherr我在同一文件夹中添加了原始文件。@TilmanHausherr你完全正确!我错误地将翻译应用于textMatrix,导致了这种效果!答案很好,但这不是他唯一的问题。他的边界框适用于所有字形,而不是单个字形。太大了。谢谢你对坐标系的提示。但正如@Tilman所说,问题还在于如何获得每个角色的边界框。我在DrawPrintTextLocations.java中找到了正确的方法。这是一个非常好的例子,谢谢分享。请参见此处的示例: