用PIL拼接多图需先计算画布尺寸:统一缩放至目标宽度1080并保持宽高比,累加新高度;用Image.new创建白底画布;paste时动态累加y_offset避免重叠;异常图片用try/except跳过;导出时JPG设quality=85和optimize=True,PNG仅用optimize=True;超65500像素需分段处理。

用 PIL.Image.new() 创建合适尺寸的画布,别硬套原图宽高
直接拼接多张照片时,画布尺寸必须提前算好。如果所有图片宽度一致(比如都是手机竖拍),就用该宽度作为画布宽;高度则是所有图片高度之和。但现实中常遇到宽高不一的情况——这时不能简单取最大宽度,否则会留白或裁剪。稳妥做法是统一缩放到相同宽度(保持宽高比),再累加高度。
- 用
Image.open()读图后,通过img.size获取原始(width, height) - 目标宽度设为
target_w = 1080,每张图等比缩放:new_h = int(img.height * target_w / img.width) - 创建画布:
canvas = Image.new('RGB', (target_w, total_new_h), 'white'),背景色建议显式指定,避免默认黑底在浅色图边缘露馅
用 paste() 逐张粘贴,注意 y 坐标累积别重叠
paste() 的第二个参数是左上角坐标元组 (x, y),x 通常为 0(居左),y 必须随前一张图高度动态累加。常见错误是写死 y=0 或每次重置为 0,结果所有图叠在一起。
- 初始化
y_offset = 0 - 循环中粘贴后立即更新:
canvas.paste(resized_img, (0, y_offset))→y_offset += resized_img.height - 若某张图加载失败(如路径错、损坏),
Image.open()会抛IOError,建议用try/except跳过并记录警告,别让整个流程中断
导出前检查 save() 的 quality 和 optimize 参数
长图文件体积容易失控——10 张 2MB 的 JPG 拼完可能达 20MB+。用 save(..., quality=85, optimize=True) 能显著压缩,且人眼几乎无感。但要注意:optimize=True 仅对 JPG 有效,PNG 不支持;而 quality 参数在 PNG 中会被忽略。
- 导出 JPG:
canvas.save('merged.jpg', quality=85, optimize=True) - 导出 PNG(需透明或无损):
canvas.save('merged.png', optimize=True)—— 此时删掉quality,否则会报ValueError: Unknown keyword argument: quality - 如果最终图超 65500 像素高(PIL 限制),保存会静默失败或截断,需提前用
if canvas.height > 65500:分段处理
横向拼接或混合方向?改 x_offset 和画布尺寸逻辑就行
上面全是竖向拼接(首尾相接)。要横向拼接,只需把逻辑从“累加高度”换成“累加宽度”,画布尺寸改为 (total_new_w, target_h),paste() 的坐标改成 (x_offset, 0)。更常见的是混合场景:比如 3 张横图排一行,下面接 2 张竖图——这时得手动分组、分别计算每行高度/宽度,再嵌套定位。没有通用公式,核心就一条:每张图的 paste() 坐标必须基于它在最终布局中的真实位置,而不是顺序索引。
立即学习“Python免费学习笔记(深入)”;
真正麻烦的不是代码量,而是缩放策略和坐标管理一旦出错,图会错位、拉伸或截断,且肉眼很难立刻定位哪张图出了问题。建议先用 2–3 张小图调试通路,再放大数据集。


















