使用 Reportlab 将旋转图像居中

Centering a rotated image using Reportlab

我试图在 Reportlab 上将旋转图像居中,但我在使用正确的位置计算时遇到问题。

这是当前代码:

from reportlab.pdfgen import canvas
from reportlab.lib.utils import ImageReader
from PIL import Image as PILImage

import requests
import math


def main(rotation):
    # create a new PDF with Reportlab
    a4 = (595.275590551181, 841.8897637795275)
    c = canvas.Canvas('output.pdf', pagesize=a4)
    c.saveState()

    # loading the image:
    img = requests.get('https://i.stack.imgur.com/dI5Rj.png', stream=True)

    img = PILImage.open(img.raw)
    width, height = img.size

    # We calculate the bouding box of a rotated rectangle
    angle_radians = rotation * (math.pi / 180)
    bounding_height = abs(width * math.sin(angle_radians)) + abs(height * math.cos(angle_radians))
    bounding_width = abs(width * math.cos(angle_radians)) + abs(height * math.sin(angle_radians))

    a4_pixels = [x * (100 / 75) for x in a4]

    offset_x = (a4_pixels[0] / 2) - (bounding_width / 2)
    offset_y = (a4_pixels[1] / 2) - (bounding_height / 2)
    c.translate(offset_x, offset_y)

    c.rotate(rotation)
    c.drawImage(ImageReader(img), 0, 0, width, height, 'auto')

    c.restoreState()
    c.save()


if __name__ == '__main__':
    main(45)

到目前为止,这是我所做的:

  1. 正在计算旋转矩形的边界(因为它会更大)
  2. 使用这些计算宽度和高度的图像中心位置(大小/2 - 图像/2)。

出现了两个我无法解释的问题:

  1. "a4" 变量以点为单位,其他一切以像素为单位。如果我将它们更改为像素以计算位置(这是合乎逻辑的,使用 a4_pixels = [x * (100 / 75) for x in a4])。对于 0 度的旋转,放置不正确。如果我将 a4 保留为点数,它会起作用... ?
  2. 如果我改变旋转,它会破坏得更多。

所以我的最后一个问题:如何计算 offset_xoffset_y 值以确保它始终居中而不考虑旋转?

谢谢! :)

当您平移 canvas 时,您实际上是在移动原点 (0,0),所有绘制操作都将与原点相关。

所以在下面的代码中,我将原点移到了页面的中间。 然后我旋转 "page" 并在 "page" 上绘制图像。无需旋转图像,因为其 canvas 轴已旋转。

from reportlab.pdfgen import canvas
from reportlab.lib.utils import ImageReader
from reportlab.lib.pagesizes import A4
from PIL import Image as PILImage
import requests

def main(rotation):
    c = canvas.Canvas('output.pdf', pagesize=A4)
    c.saveState()

    # loading the image:
    img = requests.get('https://i.stack.imgur.com/dI5Rj.png', stream=True)
    img = PILImage.open(img.raw)
    # The image dimensions in cm
    width, height = img.size

    # now move the canvas origin to the middle of the page
    c.translate(A4[0] / 2, A4[1] / 2)
    # and rotate it
    c.rotate(rotation)
    # now draw the image relative to the origin
    c.drawImage(ImageReader(img), -width/2, -height/2, width, height, 'auto')

    c.restoreState()
    c.save()

if __name__ == '__main__':
    main(45)