【问题标题】:PDFBox - obtain bounding box of rotated imagePDFBox - 获取旋转图像的边界框
【发布时间】:2017-11-20 00:20:37
【问题描述】:

我正在使用 PDFBox 并尝试旋转图像并使其在屏幕上正确定位。我正在使用的设计编辑器输出以下有关可能有用的图像的信息。

图像边界框左上角坐标(我使用左下角坐标更好地适应 PDFBox 坐标空间。)

图像旋转度数

图像宽度和高度

翻译似乎已关闭。

// Rotation
AffineTransform rotation = new AffineTransform();
rotation.rotate(Math.toRadians(360 - element.getAngle()),
    element.getLeft() + scaledWidth/2,
    adjustedYPos + scaledHeight/2);
    stream.transform(new Matrix(rotation));

// Position & scale
AffineTransform mat = new AffineTransform(scaledWidth,
        0,
        0,
        scaledHeight,
        element.getLeft(),
        adjustedYPos);

// Draw the final image
stream.drawImage(pdfImage, new Matrix(mat));

旋转基于图像的中心作为锚点。

【问题讨论】:

  • 您的代码不需要的结果是......?好的,我认为它没有正确定位,但它完全关闭了吗?还是一点点?
  • 图像靠近所需位置,并且旋转正确。该问题似乎与边界框有关。当用户创建一个设计时,输出的 json 文件会以任何旋转方式存储图像的最终边界框。就定位而言,我可以进入大致范围,但由于在用户开始旋转图像之前我们没有原始边界框,因此我们无法重建他们在尝试在 PDF 上定位图像时所采取的过程。跨度>
  • 但是你的数据引用的边界框(像往常一样)是最小的,不是吗?在这种情况下,确定所有数据应该是简单的数学运算。以及如何确定adjustedYPos
  • 是的,最小值是正确的。如果我可以访问图像的四个角位置,那么计算起来会很容易。但据我所知,我没有办法这样做吗?除非有什么我忽略了。 adjustedYPos = page.getMediaBox().getHeight() - (element.getTop() + scaledHeight)
  • 我的回答有帮助吗?

标签: java image math pdfbox


【解决方案1】:

您可以使用如下代码正确定位图像:

void placeImage(PDDocument document, PDPage page, PDImageXObject image, float bbLowerLeftX, float bbLowerLeftY, float width, float height, float angle) throws IOException {
    try (   PDPageContentStream contentStream = new PDPageContentStream(document, page, AppendMode.APPEND, true, true)   ) {
        float bbWidth = (float)(Math.abs(Math.sin(angle))*height + Math.abs(Math.cos(angle))*width);
        float bbHeight = (float)(Math.abs(Math.sin(angle))*width + Math.abs(Math.cos(angle))*height);
        contentStream.transform(Matrix.getTranslateInstance((bbLowerLeftX + .5f*bbWidth), (bbLowerLeftY + .5f*bbHeight)));
        contentStream.transform(Matrix.getRotateInstance(angle, 0, 0));
        contentStream.drawImage(image, -.5f*width, -.5f*height, width, height);
    }
}

(PlaceRotatedImage 实用方法)

此方法接受坐标,因为它们在 PDF 上下文中是有意义的,即根据给定页面的默认用户空间坐标系的坐标值和尺寸(y 值向上增加,原点任意但相当经常在左下角),(边界)由左下角给出的框,角度如逆时针弧度的数学......

如果您需要不同的参数,您可以相当轻松地调整该方法。如果你例如得到边界框的左上角而不是左下角,可以简单地减去方法中确定的边界框高度为bbHeight,计算这里使用的左下角y坐标。 p>

你可以这样使用这个方法:

PDPage page = ...;

PDRectangle mediaBox = page.getMediaBox();
float bbLowerLeftX = 50;
float bbLowerLeftY = 100;

try (   PDPageContentStream contentStream = new PDPageContentStream(document, page)   ) {
    contentStream.moveTo(bbLowerLeftX, mediaBox.getLowerLeftY());
    contentStream.lineTo(bbLowerLeftX, mediaBox.getUpperRightY());
    contentStream.moveTo(mediaBox.getLowerLeftX(), bbLowerLeftY);
    contentStream.lineTo(mediaBox.getUpperRightX(), bbLowerLeftY);
    contentStream.stroke();
}

PDImageXObject image = PDImageXObject.createFromByteArray(document, IOUtils.toByteArray(resource), "Image");
placeImage(document, page, image, bbLowerLeftX, bbLowerLeftY, image.getWidth(), image.getHeight(), (float)(Math.PI/4));
placeImage(document, page, image, bbLowerLeftX, bbLowerLeftY, .5f*image.getWidth(), .5f*image.getHeight(), 0);
placeImage(document, page, image, bbLowerLeftX, bbLowerLeftY, .25f*image.getWidth(), .25f*image.getHeight(), (float)(9*Math.PI/8));

(PlaceRotatedImage 测试testPlaceByBoundingBox)

此代码绘制与给定左下边界框坐标的左侧和底部相对应的左侧和底部线,并以给定的左下边界框角以不同的放大倍率和角度绘制图像。

结果如下:


您可以在这些答案中找到有关计算边界框大小的更多信息:

【讨论】:

  • 嘿mkl。我今天看了这个,抱歉花了一些时间。事实证明,我所指的位置数据实际上也不是边界框 top,left 而是旋转的图像 top,left。这使事情比预期的要容易。我能够稍微修改提供的实现,现在一切都按预期工作。我会将您的答案标记为正确,因为它回答了我最初的问题,但也只需要稍作修改即可处理实际结束的数据。
  • 啊,所以主要问题在于您收到的输入的文档中...... ;)
猜你喜欢
  • 1970-01-01
  • 2019-01-18
  • 1970-01-01
  • 2019-05-31
  • 2019-05-11
  • 2018-12-29
  • 2019-06-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多