You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.15 14:54:06