You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 14:45:54