【问题标题】:TextPosition Bounding Box PDFBoxTextPosition 边界框 PDFBox
【发布时间】:2019-05-31 03:20:55
【问题描述】:

我正在尝试从 TextPosition 绘制相应的字形边界框,如 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)得到以下结果

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

【问题讨论】:

  • 看看 DrawPrintTextLocations 示例,看看青色部分,它有真正的边界框(大部分时间)
  • @TilmanHausherr 我在某些情况下边界框有一些问题,有位移。我打印了为两个文件提取的边界框如果你可以看一下:drive.google.com/open?id=1aQ6TyGVAybmlNvapCodY0Rp7IRpYm5_7 我不知道为什么它发生在某些地方而不是其他地方。提前感谢
  • 这没有多大帮助,这似乎是一个截图的PDF。目前尚不清楚这是来自一个 PDF 页面还是来自多个:在“Lavande”PDF 中,右侧有位移,但左侧没有。我必须得到原始的PDF。如果这是来自几页,那么我怀疑它与cropbox有关。如果它来自一个 PDF 页面,那么我怀疑这是在错误位置隐藏文本的文本图像。
  • @TilmanHausherr 我在同一个文件夹中添加了原始文件。
  • @TilmanHausherr 你完全正确!我错误地应用了 textMatrix 的翻译,导致了这种效果!

标签: java pdf pdf-generation pdfbox


【解决方案1】:

先生。 D,

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

8.3.2.3 用户空间

用户空间坐标系应初始化为文档每一页的默认状态。页面字典中的 CropBox 条目应指定与预期输出介质(显示窗口或打印页面)的可见区域相对应的用户空间矩形。正 x 轴水平向右延伸,正 y 轴垂直向上延伸,就像在标准数学实践中一样(受页面字典中 Rotate 条目的更改)。沿 x 轴和 y 轴的单位长度由页面字典中的 UserUnit 条目 (PDF 1.6) 设置(参见表 30)。如果该条目不存在或不支持,则使用默认值 1⁄72 英寸。此坐标系称为默认用户空间。[2]

源代码

@Override 
protected void processTextPosition(TextPosition text) {
    try {
        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);

        // Invert Y axis
        Rectangle2D bounds = shape.getBounds2D();
        bounds.setRect(bounds.getX(), bounds.getY() - bounds.getHeight(), bounds.getWidth(), bounds.getHeight());

        rectangles.add(bounds);

        super.processTextPosition(text);

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

参考文献

  1. Java 2D API Concepts: Coordinates

  2. 文档管理 - 便携式文档格式 - 第 1 部分:PDF 1.7,PDF 32000-1:2008,第 8.3 节:坐标系,第 115 页

【讨论】:

  • 答案很好,但这不是他唯一的问题。他的边界框适用于所有字形,而不是单个字形。所以太大了。
  • 感谢有关坐标系的提示。但正如@Tilman 所说,问题还在于获取每个字符的边界框。我在 DrawPrintTextLocations.java 中找到了正确的方法
  • 这是一个非常简洁的例子,感谢分享。请参阅此处的示例:DrawPrintTextLocations.java
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-03-29
  • 2013-05-10
  • 1970-01-01
  • 2012-03-23
  • 2013-01-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多