【问题标题】:Get correct (rotated) image dimensions in PDF with pdfbox使用 pdfbox 在 PDF 中获取正确(旋转)的图像尺寸
【发布时间】:2016-12-30 20:18:18
【问题描述】:

我想将 PDF 渲染为图像并在其上绘制所有包含图像的边框。为此,我需要页面上图像的正确尺寸。

这是使用以下代码:

public class PrintImageLocations extends PDFStreamEngine
{
    @Override
    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("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");
                           }
            else if(xobject instanceof PDFormXObject)
            {
                PDFormXObject form = (PDFormXObject)xobject;
                showForm(form);
            }
        }
        else
        {
            super.processOperator( operator, operands);
        }
    }

}

来源:PrintImageLocations.java

输出示例:PDF 中的位置 = 535.68, 97.79052(用户空间单位)

不幸的是,我在旋转页面时遇到了问题。有很多 pdf 在“getCurrentPage().getRotation()”上返回 90。对于 90 度,我必须切换 getTranslateX 和 getTranslateY 值才能获得正确的位置,但这仅适用于 90 度。有什么很酷的矩阵转换可以用来旋转位置吗?

我认为在this 代码中,作者试图解决这个旋转问题,但是第一)我不明白转换在做什么,第二)它不能正常工作,因为在旋转后一个值为负.

【问题讨论】:

    标签: java pdfbox


    【解决方案1】:

    旋转

    您可以使用以下旋转矩阵在欧几里得空间中执行旋转。

    逆时针:

    R = ⎡ cosθ -sinθ ⎤
        ⎣ sinθ  cosθ ⎦
    

    顺时针:

    R = ⎡  cosθ  sinθ ⎤
        ⎣ -sinθ  cosθ ⎦
    

    每个矩阵都会将二维笛卡尔平面中的点围绕原点旋转角度 θ。该技术假定每个点都表示为一个列向量v。每个点的新值由R * v计算,其中*代表矩​​阵相乘。


    “负”值

    这种技术将在两个维度中至少一个维度上的至少一些点产生负值(相对于,无论如何)。为了相对于笛卡尔原点更正这一点,请将旋转后的图像“向上”平移min(y) - min(y'),将旋转后的图像“向右”平移min(x) - min(x'),其中min(d) 表示沿该维度的任意点的最小值。


    使用库

    因此您不必自己完成所有样板文件,您应该看看AffineTransform 类。

    【讨论】:

    • 1.我真的很高兴有人能理解我的问题^^
    • 2.谢谢!!!这行得通……我不明白背后的数学原理,但是“负值”-校正正是我正在寻找的……看起来它适用于所有旋转角度
    • @FlavorFlav 很高兴它对你有用!如果这解决了您的问题,请确保点赞并接受我的回答
    • @FlavorFlav “我很高兴有人理解我的问题” - 原因是这与“正确”尺寸无关(如您的问题所述)但只是在您最熟悉的坐标系中使用维度。
    【解决方案2】:

    好的...我想我可以用一些数学来解决它...不幸的是它没有用(我认为问题出在计算机面前)

    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;
    
                    Matrix ctmNew = getGraphicsState().getCurrentTransformationMatrix();
                    float imageXScale = ctmNew.getScalingFactorX();
                    float imageYScale = ctmNew.getScalingFactorY();
    
                    int rotationDegree = getCurrentPage().getRotation();
    
                    float pageHeight = this.getCurrentPage().getBBox().getHeight();
                    float pageWidth = this.getCurrentPage().getBBox().getWidth();
                    float translateX;
                    float translateY;
    
                    if (rotationDegree == 0) {
                        translateX = ctmNew.getTranslateX();
                        translateY = pageHeight - ctmNew.getTranslateY() - imageYScale;
                    } else if (rotationDegree == 90) {
                        translateX = ctmNew.getTranslateY();
                        translateY = ctmNew.getTranslateX() - imageYScale;
                    } else if (rotationDegree == 270) {
                        translateX = pageHeight - ctmNew.getTranslateY();
                        translateY = pageWidth - ctmNew.getTranslateX() - imageYScale;
                    } else if (rotationDegree == 180) {
                        translateX=pageWidth - ctmNew.getTranslateX() -imageXScale ;
                        translateY=pageHeight - ctmNew.getTranslateY() - imageYScale;
                        logger.log(Level.INFO, "image rotation 180 degree. not fully tested yet");
                    }
                    else {
                        throw new RuntimeException("");
                    }
    
                    PdfImage pdfImage = new PdfImage(objectName.getName(), translateX, translateY, imageXScale, imageYScale, image.getImage());
                    pdfImages.add(pdfImage);
    
                } else if (xobject instanceof PDFormXObject) {
                    PDFormXObject form = (PDFormXObject) xobject;
                    showForm(form);
                }
            } else {
                super.processOperator(operator, operands);
            }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-15
      相关资源
      最近更新 更多