Pillow ImageDraw绘制水印文本与Canvas显示位置偏移问题求助
解决Canvas水印与保存后图片的位置偏移问题
以下是导致偏移的核心问题及修复方案:
1. 文本绘制位置错误
在watermark.py的draw_watermark方法中,当前代码固定把文本绘制在(0,0)位置,完全忽略了计算后的坐标,这是最直接的偏移原因。同时字体大小未按原图比例调整,且文本锚点与Canvas不一致。
修复代码:
def draw_watermark(self): canvas_width = self.canvas.winfo_width() canvas_height = self.canvas.winfo_height() img = ImageTk.getimage(self.canvas_img) draw = ImageDraw.Draw(img) for text_item in self.water_mark_texts: # 按原图比例放大字体(Canvas上14号对应原图尺寸) font_size = int(14 * self.image_file.size[0] / canvas_width) font = ImageFont.truetype("arial.ttf", font_size) x, y = text_item.x, text_item.y if self.img_resized: # 将Canvas坐标转换为原图坐标:canvas坐标 × (原图尺寸 / canvas尺寸) x = x * self.image_file.width / canvas_width y = y * self.image_file.height / canvas_height text = text_item.get_text_value() # 使用"mm"锚点(中心对齐),与Tkinter的create_text默认锚点一致 draw.text((x, y), text=text, font=font, fill="white", anchor="mm", encoding="utf-8-sig") return img
2. 错误获取文本坐标
watermark_texts.py中,拖动文本时直接用鼠标位置作为文本坐标,而不是从Canvas获取文本item的实际坐标,导致记录的坐标与文本真实位置偏差。
修复代码:
def on_text_drag(self, event): global last_x, last_y dx = event.x - last_x dy = event.y - last_y self.canvas.move(self.text_item, dx, dy) last_x, last_y = event.x, event.y # 从Canvas获取文本item的真实坐标 self.x, self.y = self.canvas.coords(self.text_item)
同时初始化时也改用真实坐标:
def __init__(self, canvas, canvas_img, *args, **kwargs): self.canvas = canvas self.text_item = self.canvas.create_text(canvas_img.width() // 2, canvas_img.height() // 2, text="", fill="white", font=("arial", 14)) self.create_entry() self.is_text_editing = False self.edit_entry = None # 获取文本item的初始坐标 self.x, self.y = self.canvas.coords(self.text_item) self.canvas.tag_bind(self.text_item, "<Double-Button-1>", self.start_edit) self.canvas.tag_bind(self.text_item, "<Button-1>", self.on_text_click) self.canvas.tag_bind(self.text_item, "<B1-Motion>", self.on_text_drag)
3. 保存方法逻辑错误
watermark.py的save_photo方法中,return False写在保存代码之前,导致保存逻辑完全不会执行。
修复代码:
def save_photo(self): output = self.draw_watermark() save_dir = asksaveasfile(filetypes=FILE_TYPES, defaultextension=self.img_format) if save_dir: # 增加判断,避免用户取消保存时报错 # 保存为JPG时需转换为RGB模式,避免透明通道丢失 if save_dir.name.lower().endswith(('.jpg', '.jpeg')): output = output.convert('RGB') output.save(save_dir.name) output.show()
额外注意事项
- 确保
arial.ttf字体文件路径正确,若系统找不到可替换为本地已有的字体(如simsun.ttc支持中文)。 - 若图片缩放逻辑仍有偏差,可检查
load_image方法中图片缩放后的尺寸是否与Canvas尺寸完全匹配。
内容的提问来源于stack exchange,提问作者Hein Min Htun
相关产品推荐
相关产品推荐

