PDFBox - 获取旋转图像的边界框

时间:2017-11-20 00:20:37

标签: java image math pdfbox

我正在使用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));

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

1 个答案:

答案 0 :(得分:2)

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

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 坐标。

您可以像这样使用此方法:

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 test testPlaceByBoundingBox

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

结果如下:

screenshot

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