Python用PIL将PNG图像合成gif时如果背景为透明时图像出现重影的解决办法
最近在用PIL合成PNG图像为GIF时,因为需要透明背景,所以就用putpixel的方法替换背景为透明,但是在合成GIF时,图像出现了重影,在网上查找了GIF的相关资料:GIF相关资料 其中有对GIF帧数处理的说明,需要在GIF图像的header中设置disposal的处置方法
然后我们可以查看PIL库中关于GIF的定义文件GifImagePlugin.py
1 disposal = int(im.encoderinfo.get("disposal", 0)) 2 3 if transparent_color_exists or duration != 0 or disposal: 4 packed_flag = 1 if transparent_color_exists else 0 5 packed_flag |= disposal << 2 6 if not transparent_color_exists: 7 transparency = 0 8 9 fp.write( 10 b"!" 11 + o8(249) # extension intro 12 + o8(4) # length 13 + o8(packed_flag) # packed fields 14 + o16(duration) # duration 15 + o8(transparency) # transparency index 16 + o8(0)
其中有一段关于Disposal的定义,如果保存时不设置disposal属性则默认为0,即不使用处理方法,所以每一张PNG文件都被保留成了背景,也就是我们看到的重影,所以我们在合成GIF时,需要设置disposal值
原图:
下面是生成透明背景PNG图像代码:
1 from PIL import Image 2 3 img = Image.open("dabai.gif") 4 try: 5 flag = 0 6 while True: 7 #获取每一帧 8 img.seek(flag) 9 #保存 10 img.save("pics/{}.png".format(flag)) 11 pic = Image.open("pics/{}.png".format(flag)) 12 #转化 13 pic = pic.convert("RGBA") 14 #替换背景为透明 15 color = pic.getpixel((0,0)) 16 for i in range(pic.size[0]): 17 for j in range(pic.size[1]): 18 dot = (i,j) 19 rgba = pic.getpixel(dot) 20 if rgba == color: 21 rgba = rgba[:-1] + (0,) 22 pic.putpixel(dot, rgba) 23 #保存 24 pic.save("pics/{}.png".format(flag)) 25 flag +=1 26 except BaseException as e: 27 pass
合成GIF图像:
1 #!/usr/bin/env python 2 # -*- coding: utf-8 -*- 3 4 from PIL import Image 5 import os 6 photo_list = [] 7 #获取保存的PNG图像 8 pic_list = os.listdir("pics/") 9 #对图像List排序,防止图像位置错乱 10 pic_list.sort(key=lambda x:int(x[:-4])) 11 for k in pic_list: 12 pic_p = Image.open("pics/{}".format(k)) 13 photo_list.append(pic_p) 14 #保存图像,disposal可以为2或者3,但是不能为1或0,切记,其他自定义未尝试 15 photo_list[0].save("dabai_new.gif", save_all=True, append_images=photo_list[1:],duration=40,transparency=0,loop=0,disposal=3)
合成后图像,背景已变成透明而且未出现重影