如何将旋转后的PIL图片精准粘贴到目标位置中心?
解决PIL旋转文本图片粘贴位置偏移问题
核心问题出在旋转时默认以图片左上角为中心,且旋转后图片尺寸会自动扩展以容纳完整内容,直接用原文本尺寸的一半计算偏移完全不匹配实际情况。以下是精准定位的具体步骤和代码示例:
关键解决要点
- 生成带透明背景的文本画布,避免旋转后多余背景干扰定位
- 旋转时开启
expand=True,获取包含完整旋转内容的图片 - 以文本中心为旋转基准,确保旋转后文本中心与画布中心重合
- 用旋转后图片的实际尺寸计算偏移量,而非原文本尺寸
代码实现
1. 导入依赖
from PIL import Image, ImageDraw, ImageFont import math
2. 生成旋转文本的工具函数
def get_rotated_text_img(text, font, angle): # 获取文本实际宽高(排除字体自带的空白偏移) bbox = font.getbbox(text) text_w = bbox[2] - bbox[0] text_h = bbox[3] - bbox[1] # 创建足够大的透明画布,将文本绘制在画布中心 canvas_w, canvas_h = text_w * 2, text_h * 2 text_canvas = Image.new("RGBA", (canvas_w, canvas_h), (0, 0, 0, 0)) draw = ImageDraw.Draw(text_canvas) draw_pos = ((canvas_w - text_w) // 2, (canvas_h - text_h) // 2) draw.text(draw_pos, text, font=font, fill=(0, 0, 0, 255)) # 旋转画布,expand=True自动适配旋转后的尺寸 rotated_img = text_canvas.rotate(angle, expand=True, resample=Image.Resampling.BICUBIC) # 返回旋转后的图片,以及图片中心的偏移量(用于定位) return rotated_img, (rotated_img.width // 2, rotated_img.height // 2)
3. 主流程中精准粘贴
# 初始化基础画布 base_img = Image.new("RGB", (800, 800), (255, 255, 255)) draw = ImageDraw.Draw(base_img) cx, cy = 400, 400 # 中心坐标 radius = 300 # 辐射线半径 # 加载字体(确保本地存在Roboto-Regular.ttf) font = ImageFont.truetype("Roboto-Regular.ttf", 24) # 遍历绘制辐射线和数字 for i in range(12): # 计算当前辐射线的角度(弧度转角度) theta = math.radians(i * 30) # 计算辐射线末端坐标 end_x = cx + radius * math.cos(theta) end_y = cy + radius * math.sin(theta) # 绘制辐射线 draw.line([(cx, cy), (end_x, end_y)], fill=(0, 0, 0), width=2) # 生成旋转后的数字图片(文本旋转角度与辐射线角度匹配,可根据需求调整+90) rotated_text, (center_w, center_h) = get_rotated_text_img(str(i+1), font, math.degrees(theta)) # 计算粘贴位置:末端坐标减去图片中心偏移,让文本中心与末端重合 paste_x = int(end_x - center_w) paste_y = int(end_y - center_h) # 粘贴时传入透明通道作为mask,避免覆盖背景 base_img.paste(rotated_text, (paste_x, paste_y), rotated_text) base_img.save("result.png")
额外调整提示
- 字体路径要确保正确,本地IDE中可直接用同目录文件名或绝对路径
- 文本旋转角度可按需调整,比如想要文本垂直于辐射线,可改为
math.degrees(theta) + 90 - 如果文本仍有细微偏移,可微调
draw_pos的坐标,修正字体自带的基线偏移
内容的提问来源于stack exchange,提问作者kenny
相关产品推荐
相关产品推荐

