使用Apache PDFBox获取PDF中图片绝对位置时总返回0,0如何解决
Apache PDFBox 获取PDF图片绝对位置的解决方案
问题根因
- 你当前直接读取CTM的平移、缩放分量的方式不适用于多变换拼接的场景:PDF中绘制图片时通常会通过多次矩阵拼接实现平移、缩放、旋转效果,此时CTM的
getTranslateX()/getTranslateY()返回的不是最终绝对坐标,单独取缩放因子也无法得到真实显示尺寸 - 你看到的1x1显示尺寸是因为图片被先映射到1x1单位矩形,再通过CTM整体变换到目标大小,拆分矩阵分量会丢失上下文信息
正确实现逻辑
图片默认绘制在用户空间(0,0)到(1,1)的矩形范围内,我们只需要用当前CTM对这个矩形的顶点做坐标变换,就能得到图片在页面上的绝对位置与真实尺寸:
- 变换后的
(0,0)点即为图片左下角的绝对坐标(PDF默认坐标原点为页面左下角) - 计算相邻顶点的距离即可得到图片实际显示的宽高,支持带旋转、剪切的场景
修改后的核心代码
你只需要替换原代码中CTM取值相关的部分即可,完整的修改后逻辑如下:
protected void processOperator( Operator operator, List<COSBase> operands) throws IOException { String operation = operator.getName(); if( "Do".equals(operation) ) { COSName objectName = (COSName) operands.get( 0 ); PDXObject xobject = getResources().getXObject( objectName ); if( xobject instanceof PDImageXObject) { PDImageXObject image = (PDImageXObject)xobject; int imageWidth = image.getWidth(); int imageHeight = image.getHeight(); System.out.println("\nImage [" + objectName.getName() + "]"); Matrix ctmNew = getGraphicsState().getCurrentTransformationMatrix(); // 计算图片四个顶点的实际页面坐标 Point2D.Float leftBottom = ctmNew.transformPoint(0, 0); Point2D.Float rightBottom = ctmNew.transformPoint(1, 0); Point2D.Float leftTop = ctmNew.transformPoint(0, 1); // 绝对坐标(默认以页面左下角为原点) float absX = leftBottom.x; float absY = leftBottom.y; // 若需要以页面左上角为原点,替换为下方代码(page为当前处理的PDPage对象,需提前传入你的解析类) // float absY = page.getMediaBox().getHeight() - leftBottom.y; // 计算实际显示尺寸 float displayWidth = (float) leftBottom.distance(rightBottom); float displayHeight = (float) leftBottom.distance(leftTop); System.out.println("position in PDF = " + absX + ", " + absY + " in user space units"); System.out.println("raw image size = " + imageWidth + ", " + imageHeight + " in pixels"); System.out.println("displayed size = " + displayWidth + ", " + displayHeight + " in user space units"); } else if(xobject instanceof PDFormXObject) { PDFormXObject form = (PDFormXObject)xobject; showForm(form); } } else { super.processOperator( operator, operands ); } }
注意事项
- 你代码中已有的
showForm(form)逻辑是正确的,PDFBox会自动累积Form XObject的变换矩阵,无需额外处理嵌套的Form对象 - 坐标单位为用户空间单位,默认1单位等于1/72英寸,和PDF页面尺寸单位一致
内容的提问来源于stack exchange,提问作者gbelin
相关产品推荐
相关产品推荐

