PDFBox没有返回正确的图像大小

时间:2016-01-27 07:29:15

标签: pdfbox

我是PDFBox的新手,并坚持找到以英寸为单位的图像高度。经过几次搜索,这是我正在使用的代码片段:

PDResources resources = aPdPage.findResources();
        graphicsState = new PDGraphicsState(aPdPage.findCropBox());
        pageWidth = aPdPage.findCropBox().getWidth() / 72;
        pageHeight = aPdPage.findCropBox().getHeight() / 72;
        @SuppressWarnings("deprecation")
        Map<String, PDXObjectImage> imageObjects = resources.getImages();
        if (null == imageObjects || imageObjects.isEmpty())
            return;
        for (Map.Entry<String, PDXObjectImage> entryxObjects : imageObjects.entrySet()) {

            PDXObjectImage image = entryxObjects.getValue();
        //  System.out.println("bits per component: " + image.getBitsPerComponent());
            Matrix ctmNew = graphicsState.getCurrentTransformationMatrix();
            float imageXScale = ctmNew.getXScale();
            float imageYScale = ctmNew.getYScale();
            System.out.println("position = " + ctmNew.getXPosition() + ", " + ctmNew.getYPosition());
            // size in pixel
            System.out.println("size = " + image.getWidth() + "px, " + image.getHeight() + "px");
            // size in page units
            System.out.println("size = " + imageXScale + "pu, " + imageYScale + "pu");
            // size in inches 
            imageXScale /= 72;
            imageYScale /= 72;
            System.out.println("size = " + imageXScale + "in, " + imageYScale + "in");
            // size in millimeter
            imageXScale *= 25.4;
            imageYScale *= 25.4;
            System.out.println("size = " + imageXScale + "mm, " + imageYScale + "mm");

            System.out.printf("dpi  = %.0f dpi (X), %.0f dpi (Y) %n", image.getWidth() * 72 / ctmNew.getXScale(), image.getHeight() * 72 / ctmNew.getYScale());

        }

但价值不是以英寸为单位。 pu中的imageXScale值始终为0.1。

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:2)

首先,您需要了解通常如何在PDF中使用位图图像:

在PDF中,页面对象包含一组所谓的资源,其中包括位图图像资源,字体资源......

您可以像以前一样检查这些资源:

PDResources resources = aPdPage.findResources();
@SuppressWarnings("deprecation")
Map<String, PDXObjectImage> imageObjects = resources.getImages();
if (null == imageObjects || imageObjects.isEmpty())
    return;
for (Map.Entry<String, PDXObjectImage> entryxObjects : imageObjects.entrySet())
{
    PDXObjectImage image = entryxObjects.getValue();
    System.out.println("size = " + image.getWidth() + "px, " + image.getHeight() + "px");
}

但这只会为您提供图像的像素尺寸,因为它们在页面资源中可用。

当这样的资源被绘制到页面上时,执行此操作的操作实际上首先将其缩小到1x1单位的正方形并绘制这个按比例缩小的版本。

您在屏幕和纸上拥有合理尺寸的图像的原因是,绘图操作员在PDF中工作的方式受所谓的当前图形状态的影响。此图形状态包含当前填充颜色线宽等信息...特别是它还包含所谓的当前转换矩阵它定义了一些操作绘制的所有内容应该如何拉伸,旋转,倾斜,翻译,......转换。

绘制位图图像时的常用操作顺序如下所示:

  • ...
  • 存储 当前图形状态的临时副本
  • 通过缩放变换更改当前变换矩阵,缩放变换将x坐标乘以所需宽度,将y坐标乘以要绘制的图像的所需高度,
  • 绘制资源中引用的图片
  • 将当前图形状态恢复为临时存储的值
  • ...

因此,要了解页面上图像的尺寸,您必须知道执行图像绘制操作时的当前变换矩阵

另一方面,您的代码使用来自新实例化图形状态的当前转换矩阵,其中默认值为的所有值。因此,您的代码会打印关于如何在页面上缩放图像的错误信息。

要获取正确的信息,您必须解析为创建文档页面而执行的操作序列。

这正是PDFBox PrintImageLocations示例的作用:它处理页面内容流(包含所有这些操作),更新当前图形状态值的副本,以及何时查看操作绘制位图图像时,它会在当时使用当前变换矩阵的值:

protected void processOperator( PDFOperator operator, List arguments ) throws IOException
{
    String operation = operator.getOperation();
    if( INVOKE_OPERATOR.equals(operation) )
    {
        COSName objectName = (COSName)arguments.get( 0 );
        Map<String, PDXObject> xobjects = getResources().getXObjects();
        PDXObject xobject = (PDXObject)xobjects.get( objectName.getName() );
        if( xobject instanceof PDXObjectImage )
        {
            PDXObjectImage image = (PDXObjectImage)xobject;
            PDPage page = getCurrentPage();
            int imageWidth = image.getWidth();
            int imageHeight = image.getHeight();
            double pageHeight = page.getMediaBox().getHeight();
            System.out.println("*******************************************************************");
            System.out.println("Found image [" + objectName.getName() + "]");

            Matrix ctmNew = getGraphicsState().getCurrentTransformationMatrix();
            ...
            [calculate dimensions and rotation of image on page]
            ... 

因此,对于您的任务,PDFBox示例应该是一个很好的起点。