使用Pillow裁剪GIF为正方形时触发无效尺寸错误的技术求助
解决Pillow裁剪GIF并保存为WebP时的帧尺寸错误问题
错误原因分析
- 裁剪坐标为浮点数:Pillow的
crop()方法要求传入的坐标必须是整数,你计算得到的111.0是浮点数,会导致裁剪后的帧尺寸不符合要求。 - 帧尺寸不一致:保存WebP动图时,所有帧(包括基础图像和追加的帧)必须尺寸一致。你的代码中用原尺寸的
im作为基础保存,而追加的是裁剪后的帧,尺寸不匹配触发错误。 - 变量名冲突:你直接修改了原图像的
width和height变量,导致后续逻辑中变量含义混乱,容易引发计算错误。
修复后的代码
from PIL import Image, ImageSequence im = Image.open('950_kb.gif') orig_width, orig_height = im.size print(f"原GIF尺寸: {orig_width, orig_height}") # 计算正方形裁剪的参数,确保所有值为整数 if orig_width != orig_height: if orig_width > orig_height: crop_size = orig_height left = (orig_width - crop_size) // 2 top = 0 else: crop_size = orig_width left = 0 top = (orig_height - crop_size) // 2 right = left + crop_size bottom = top + crop_size crop_box = (left, top, right, bottom) print(f"裁剪参数: {crop_box}") if getattr(im, "is_animated", False): frames = [] for frame in ImageSequence.Iterator(im): # 复制帧避免修改原图像,同时裁剪为正方形 cropped_frame = frame.copy().crop(crop_box) frames.append(cropped_frame) # 以第一帧为基础保存所有裁剪后的帧 if frames: frames[0].save( 'test.webp', format="webp", save_all=True, append_images=frames[1:], loop=0, duration=im.info.get('duration', 100) # 保留原GIF的帧间隔 ) else: cropped_im = im.crop(crop_box) cropped_im.save('test.webp', format="webp")
关键修复点说明
- 整数裁剪坐标:用整数除法
//计算坐标,确保crop_box内的所有值都是整数,符合Pillow的要求。 - 统一帧尺寸:保存时以裁剪后的第一帧作为基础,追加剩余的裁剪后帧,保证所有帧尺寸完全一致。
- 保留原GIF属性:添加
duration参数保留原GIF的帧间隔,让动图播放速度和原文件一致。 - 避免变量冲突:使用
orig_width、orig_height、crop_size等新变量,避免覆盖原图像尺寸变量。
内容的提问来源于stack exchange,提问作者kipteam
相关产品推荐
相关产品推荐

