【问题标题】:Apache PDFBox rotate PDImageXObjectApache PDFBox 旋转 PDImageXObject
【发布时间】:2014-09-30 11:32:27
【问题描述】:

我正在玩 2.0.0-SNAPSHOT,我想将页面设置为横向并旋转我的图片。所以我已经完成了page.setRotation(90);

使用 PDFBox 和 AffineTransform 似乎存在错误

这段代码并没有像我期望的那样做任何事情:

AffineTransform at = new AffineTransform(w, 0, 0, h, 20, 20);
at.translate(0.5, 1);
at.rotate(Math.toRadians(90));

宽度和高度必须很小才能将图像保持在页面上,自身旋转会挤压图像,并在旋转之前平移似乎会放大图像。

这是一个错误,还是我只是不了解 PDFBox?

【问题讨论】:

  • 所以你创建了一个转换矩阵。但是你如何使用它?您希望您的转换值产生什么影响?
  • 按照我的第一句话:“我想将页面设置为横向并旋转我的图片”。但是平移和旋转都具有可笑的缩放效果。
  • @djb:我已经更新了我的答案。昨天没有测试90°的页面旋转,使用的时候,得到了你描述的效果。
  • @djb 如果提供的示例代码可以很容易地用于重现问题,这通常会很有帮助。您只提供设置页面旋转和生成仿射变换的代码,而不是如何使用该仿射变换。 Tilman 费心编写这样的代码,而其他人则没有。如果您提供了代码,您可能会收到更多回复。
  • @mkl - 我确实有原始的轮换代码,蒂尔曼让我清理我的问题。旋转代码将其从屏幕某处旋转出来,所以我留下的示例只是显示了我所描述的奇怪错误。

标签: java pdf matrix transformation pdfbox


【解决方案1】:

不要做额外的翻译,而是在创建 AT 时放置翻译。请记住,旋转是围绕左下轴的,因此将宽度 w 添加到 x 位置。

    PDPage page = new PDPage();
    document.addPage(page);
    page.setRotation(90);
    PDPageContentStream contentStream = new PDPageContentStream(document, page);

    int x = 150;
    int y = 300;

    // draw unrotated
    contentStream.drawXObject(ximage, x, y, ximage.getWidth() / 2, ximage.getHeight() / 2);

    // draw 90° rotated, placed on the right of the first image
    AffineTransform at = new AffineTransform(ximage.getHeight() / 2, 0, 0, ximage.getWidth() / 2, x + ximage1.getWidth(), y);
    at.rotate(Math.toRadians(90));
    contentStream.drawXObject(ximage, at);

这将绘制图像两次,一次正常,一次旋转 90°,并定位到右侧。 "/2" 用于缩放 50%,当然你可以使用另一个因子。请注意,“/2”不用于初始 x 位置,因为(缩放的)宽度需要两次。一次定位到旧位置(因为轴!),一次将其向右移动以使图像不重叠。

还要注意 getHeight() 和 getWidth() 是相反的,用于页面旋转。

【讨论】:

  • 啊哈,我解决了。不过,你几乎拥有它。这就是诀窍:AffineTransform at = new AffineTransform(ximage.getWidth() / 2, 0, 0, ximage.getHeight() / 2, x + ximage1.getWidth(), y);
【解决方案2】:
AffineTransform at = new AffineTransform(w, 0, 0, h, 20, 20);
at.translate(0.5, 1);
at.rotate(Math.toRadians(90));

宽度和高度必须很小才能将图像保持在页面上,自身旋转会挤压图像,并且在旋转似乎会放大图像之前进行平移。

这是一个错误,还是我只是不了解 PDFBox?

这不是错误,它只是数学问题。您只需要注意,如果您有一个AffineTransform at,然后调用at.translate(...)at.rotate(...),您不会将仿射变换的平移/旋转部分设置为给定值,而是而是将您的转换替换为前一个转换和平移/旋转的组合

这意味着例如

AffineTransform at = new AffineTransform(w, 0, 0, h, 20, 20);
at.translate(0.5, 1);

不一样

AffineTransform at = new AffineTransform(w, 0, 0, h, 20.5, 21);

如您所料,但相反

AffineTransform at = new AffineTransform(w, 0, 0, h, 20 + w/2, 20 + h);

这就是为什么 宽度和高度必须很小才能将图像保持在页面上 - translate(0.5, 1) 否则会推得很远。

由于您构成转换的顺序很重要,如果您按此顺序创建转换,您可能会更开心:

AffineTransform at = AffineTransform.getTranslateInstance(0.5, 1);
at.rotate(Math.toRadians(90));
af.concatenate(new AffineTransform(w, 0, 0, h, 20, 20));

PS:正如 Tilman 所说:请记住,旋转是围绕左下角进行的,所以这个构图也会在屏幕外旋转。只需将h+20 添加到初始平移的 x 坐标即可。

【讨论】:

  • 啊,好吧,我确实认为翻译是在添加值。正如蒂尔曼的回复中提到的,我现在已经解决了 - 我使用了他的答案,但不得不交换高度和宽度。但是您对矩阵信息也很有帮助,谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-12-22
相关资源
最近更新 更多