使用ReportLab实现旋转图像居中:布局计算问题求助
解决ReportLab旋转图像居中显示的问题
我明白你在ReportLab里旋转图像后,搞不定居中布局的计算——这事儿确实容易绕晕,毕竟旋转后图像的“占位大小”会变,直接用原尺寸算位置肯定不对。咱们一步步来捋清楚:
核心问题:旋转后的图像尺寸变化
图像旋转θ角度后,它的外接矩形宽高会变成:
- 旋转后宽度 = 原宽×cosθ + 原高×sinθ
- 旋转后高度 = 原宽×sinθ + 原高×cosθ
(这里θ要转成弧度计算)
如果忽略这个变化,直接按原图像尺寸算居中,旋转后的图像肯定会偏离页面中心。
修正后的代码实现
下面是调整后的代码,我加了详细注释,重点处理了旋转后的尺寸计算和坐标变换:
from reportlab.pdfgen import canvas from reportlab.lib.utils import ImageReader from PIL import Image as PILImage import requests import math from io import BytesIO # 新增,用来处理请求返回的图像数据 def main(rotation): # A4页面尺寸(单位:点,1点=1/72英寸) a4_width, a4_height = (595.275590551181, 841.8897637795275) c = canvas.Canvas('output.pdf', pagesize=(a4_width, a4_height)) c.saveState() # 加载图像:请求图片转成PIL格式,再用ReportLab的ImageReader处理 img_response = requests.get('https://i.ssta...') # 替换成你的实际图片链接 pil_img = PILImage.open(BytesIO(img_response.content)) img_reader = ImageReader(pil_img) # 获取图像原始尺寸(像素),转成ReportLab的点单位(假设图像DPI为72,和ReportLab默认一致) # 如果图像DPI不是72,需要调整:点 = 像素 × 72 / 图像DPI orig_pix_w, orig_pix_h = pil_img.size img_w = orig_pix_w img_h = orig_pix_h # 把旋转角度转为弧度(math库的三角函数需要弧度) rotation_rad = math.radians(rotation) # 计算旋转后外接矩形的宽高 rotated_w = abs(img_w * math.cos(rotation_rad)) + abs(img_h * math.sin(rotation_rad)) rotated_h = abs(img_w * math.sin(rotation_rad)) + abs(img_h * math.cos(rotation_rad)) # 计算页面中心坐标 page_center_x = a4_width / 2 page_center_y = a4_height / 2 # 关键坐标变换:先把画布原点移到页面中心,再旋转画布,最后绘制图像 # 这样旋转的中心就是页面中心,图像旋转后自然居中 c.translate(page_center_x, page_center_y) c.rotate(rotation) # 绘制图像时,让图像的中心和画布原点(页面中心)重合 c.drawImage(img_reader, -rotated_w/2, -rotated_h/2, width=rotated_w, height=rotated_h) c.restoreState() # 恢复画布状态,不影响后续内容 c.save() # 测试:旋转45度的情况 main(45)
关键细节说明
- 坐标变换顺序:一定要先
translate到页面中心,再rotate——如果先旋转再平移,旋转的原点还是画布左下角,图像会跑偏。 - 图像单位转换:如果你的图像DPI不是72(比如常见的96DPI),记得把像素转成点,比如:
dpi_x, dpi_y = pil_img.info['dpi'] img_w = orig_pix_w * 72 / dpi_x img_h = orig_pix_h * 72 / dpi_y - 状态保存与恢复:用
saveState()和restoreState()隔离当前的画布变换,避免影响PDF里的其他内容。
内容的提问来源于stack exchange,提问作者Cyril N.
相关产品推荐
相关产品推荐

