Python Telegram图片水印机器人 实现保留原图尺寸的无降质处理
冗余缩放逻辑排查与改造方案
问题根源
输出尺寸小于预期的问题来自两个链路的冗余逻辑:
- 本地PIL处理模块中遗留了针对原图主体的缩放代码,未严格区分“水印尺寸适配”和“原图画布缩放”的逻辑边界
- Telegram Bot 取图/回传环节未跳过平台自带的多分辨率缩略图加载、自动压缩逻辑,实际加载的源图本身尺寸就偏小,回传时又被平台二次压缩
分模块改造步骤
PIL图片处理模块(核心改造)
- 直接删除所有针对原始图片主体的缩放调用:移除代码中所有对原图Image对象执行的
resize()、thumbnail()、reduce()操作,这类操作是直接缩小输出尺寸的根源 - 保留必要的水印尺寸适配逻辑:仅保留以原图宽高为基准的水印尺寸计算逻辑——根据原图比例计算适配的水印字体大小、水印整体占比、摆放位置,不对原图画布做任何像素层面的尺寸修改
- EXIF方向校正无缩放改造:使用
ImageOps.exif_transpose()完成方向校正,该操作仅对齐旋转方向,不会改变原图像素总尺寸,禁止在校正流程中额外添加尺寸换算 - 导出环节消除隐形缩放:保存图片时显式保留原图像素尺寸、原DPI参数,避免保存流程自动压缩尺寸,参考导出实现:
processed_img.save( output_path, format="JPEG", quality=95, dpi=processed_img.info.get("dpi", (300, 300)), subsampling=0 )
Telebot 主逻辑模块改造
- 取图环节锁定最高分辨率源图:Telegram 消息返回的photo列表按分辨率从小到大排序,跳过靠前的缩略图条目,直接取列表最后一个最高分辨率的条目作为处理源,参考实现:
@bot.message_handler(content_types=['photo']) def handle_incoming_photo(message): # 取最高分辨率的图片条目 highest_res_photo = message.photo[-1] file_meta = bot.get_file(highest_res_photo.file_id) source_bytes = bot.download_file(file_meta.file_path) - 回传环节关闭平台自动压缩:
send_photo通道会触发Telegram服务端默认的图片缩放(最长边1280px),改为用send_document通道发送本地处理完成的图片文件,跳过平台自动缩放压缩,保证回传文件和本地处理结果的尺寸完全一致。
效果验证
- 流程插入尺寸校验:在PIL模块加载完原图、合成完水印、导出前三个节点分别打印图片宽高数值,确认三个节点的尺寸和用户上传的原图原始尺寸完全一致
- 逻辑边界校验:确认代码中所有涉及尺寸修改的操作,作用对象都是水印图层,不存在反向修改原图画布尺寸的逻辑
- 端到端测试:将本地处理完成的带水印文件和用户上传的原图做像素尺寸、画质对比,确认无尺寸差、无预期外的画质损失
内容的提问来源于stack exchange,提问作者Imtryingbigtime
相关产品推荐
相关产品推荐

