使用pdfbox以PDF格式获取正确(旋转)的图像尺寸

时间:2016-12-29 04:44:32

标签: java pdfbox

我希望将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代码中,作者试图解决这个旋转问题,但是1)我不明白转换正在做什么和第2)它不能正常工作,因为在旋转一个值之后否定。

2 个答案:

答案 0 :(得分:0)

轮换

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

逆时针:

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 :(得分:0)

好的......我以为我可以用一些数学来运行它...不幸的是它不起作用(我觉得问题是坐在电脑前)

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);
        }
}