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");
在页面上绘制的图像的宽度和高度,以毫米为单位,假设用户空间单位宽度为 1/72 英寸,默认值。可能会出现负值,见上文。
因此,此处的负值具有与任何 DPI 属性无关的含义(镜像或 180° 旋转)。因此,要计算 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] 按原样返回,可能为负数。
一致的实现要么总是删除符号,要么总是尝试确定有意义的符号
此外,计算有点简单,因为它只考虑可以写成缩放和旋转乘积的变换矩阵。这些是非常常见的类型,但目前还不是所有可能的类型。