在java中获取图像的负DPI

时间:2016-04-25 12:35:41

标签: java pdf pdfbox

为某些pdf获取负图像XScale和imageYScale 同时将pdf转换为图像并找到其DPI。 Jar使用的是pdfbox1.8.8和iText。

找到图像Im0 位置= 602.64,451.08 尺寸= 837px,626px尺寸= -212.59799mm,-159.131mm

必须为0的位置有一些价值。 无法发现问题

1 个答案:

答案 0 :(得分:0)

OP提到他使用 pdfbox1.8.8和iText 但没有提供进一步说明他如何使用这些库中的任何一个从他的PDF中检索值。

考虑单词 imageXScale imageYScale 以及位置和大小输出,我会假设他已使用PrintImageLocations PDFBox example

PrintImageLocations输出的含义

此示例为页面上某处绘制的位图图像执行以下输出:

System.out.println("Found image [" + objectName.getName() + "]");

图像资源的名称

Matrix ctmNew = getGraphicsState().getCurrentTransformationMatrix();
float imageXScale = ctmNew.getScalingFactorX();
float imageYScale = ctmNew.getScalingFactorY();

// position in user space units. 1 unit = 1/72 inch at 72 dpi
System.out.println("position in PDF = " + ctmNew.getTranslateX() + ", " + ctmNew.getTranslateY() + " in user space units");

定位点的位置,即在页面上绘制图像的原始左下角的位置。

// raw size in pixels
System.out.println("raw image size  = " + imageWidth + ", " + imageHeight + " in pixels");

图像资源的原始宽度和高度(以像素为单位)。总是非负面的。

// displayed size in user space units
System.out.println("displayed size  = " + imageXScale + ", " + imageYScale + " in user space units");

页面上绘制的图像的宽度和高度。负值可能意味着图像资源不是从锚点向右和向上绘制,而是向左和向下绘制。

// displayed size in inches at 72 dpi rendering
imageXScale /= 72;
imageYScale /= 72;
System.out.println("displayed size  = " + imageXScale + ", " + imageYScale + " in inches at 72 dpi rendering");

在页面上绘制的图像的宽度和高度,以英寸为单位,假设用户空间单位宽度为1/72英寸(默认值)。可能会出现负值,见上文。

// displayed size in millimeters at 72 dpi rendering
imageXScale *= 25.4;
imageYScale *= 25.4;
System.out.println("displayed size  = " + imageXScale + ", " + imageYScale + " in millimeters at 72 dpi rendering");

在页面上绘制的图像的宽度和高度,以mm为单位,假定用户空间单位宽度为1/72英寸(默认值)。可能会出现负值,见上文。

因此,这里的负值具有意义(镜像或180°旋转),这对于任何DPI属性没有影响。因此,要计算DPI值,请仅使用绝对值,忽略符号。

PDFBox中的不一致

上面使用的x和y缩放因子来自当前的变换矩阵,如下所示:

/**
 * Returns the x-scaling factor of this matrix. This is calculated from the scale and shear.
 *
 * @return The x-scaling factor.
 */
public float getScalingFactorX()
{
    float xScale = single[0];

    /**
     * BM: if the trm is rotated, the calculation is a little more complicated
     *
     * The rotation matrix multiplied with the scaling matrix is:
     * (   x   0   0)    ( cos  sin  0)    ( x*cos x*sin   0)
     * (   0   y   0) *  (-sin  cos  0)  = (-y*sin y*cos   0)
     * (   0   0   1)    (   0    0  1)    (     0     0   1)
     *
     * So, if you want to deduce x from the matrix you take
     * M(0,0) = x*cos and M(0,1) = x*sin and use the theorem of Pythagoras
     *
     * sqrt(M(0,0)^2+M(0,1)^2) =
     * sqrt(x2*cos2+x2*sin2) =
     * sqrt(x2*(cos2+sin2)) = <- here is the trick cos2+sin2 is one
     * sqrt(x2) =
     * abs(x)
     */
    if( !(single[1]==0.0f && single[3]==0.0f) )
    {
        xScale = (float)Math.sqrt(Math.pow(single[0], 2)+
                                  Math.pow(single[1], 2));
    }
    return xScale;
}

Excerpt from Matrix.java

虽然显然有人确实对此有所了解(看评论!),但实施有些不一致:

  • 如果single[1]single[3]中存在非零值,则if块中的计算会产生非负方法结果。
  • 对于single[1]single[3]中的零值,single[0]按原样返回,可能是否定的。

一致的实施要么总是删除标志,要么总是试图确定一个有意义的标志

此外,计算有点简单,因为它只考虑可以作为缩放和旋转的乘积写入的变换矩阵。这些是非常常见的类型,但到目前为止并非所有可能的类型。