python 2.7实现gif图片缩小

注:本文基于CentOS 7.2系统操作,使用的python版本为:2.7.5

1、背景

最近在发gif表情的时候发现有些动图太大了,一发就占了一整屏,不太舒服,想着有啥办法能缩小gif的大小,于是乎想起了python。

大概了解了一下,需要使用到PIL的Image和ImageSequence模块,但是这里有一个天坑,让我折腾了一天的时间。。。

那就是:原生PIL不支持gif的保存,需要使用pillow。

因为这,我缩小后的gif只有一帧,还动不了,我还以为是我代码哪里错了,so sad。

2、安装pillow

pip install pillow

对,就只需要这么一个语句。

3、代码

废话不多说,上代码。

#!/usr/bin/env python

from PIL import Image, ImageSequence
import sys, os

if len(sys.argv) < 3:
    print("input invalid!")
    print("you need input ingif and outgif.")
    exit(1)

inf = sys.argv[1]
outf = sys.argv[2]

gif = Image.open(inf)
dura = gif.info['duration']
imgs = [f.copy() for f in ImageSequence.Iterator(gif)]

index = 0
imglist = []
os.mkdir("images")
for frame in imgs:
    frame.save("./images/%d.png" % index)
    im = Image.open("./images/%d.png" % index)
    im.thumbnail((128,128), Image.ANTIALIAS)
    imglist.append(im)
    index += 1

os.system("rm -rf ./images")

imglist[0].save(outf, 'gif', save_all=True, append_images=imglist[1:], loop=0, duration=dura)

4、重点说明

gif图片压缩的思路大概就是:获取gif的每一帧,将每一帧图片缩小,然后将缩小的图片重新合成gif图片。

1、获取帧信息
使用ImageSequence模块的迭代器去遍历gif动图的每一帧,然后放到imgs列表里。

imgs = [f.copy() for f in ImageSequence.Iterator(gif)]

上述语句相当于下面的简写:

for f in ImageSequence.Iterator(gif):
    imgs.append(f.copy())

2、将帧信息保存为静态图片

frame.save("./images/%d.png" % index)

上一个步骤我们已经获取了动图的帧信息,这里使用save方法,将帧信息保存为png图片。

是否能保存为jpg格式呢?答案是不能,如果需要将其保存为jpg格式,需要先将帧信息转成RGB格式,然后才能保存为jpg格式。

frame = frame.convert('RGB')  
frame.save("./images/%d.jpg" % index)  

这是什么原因呢?据我考证(不一定正确),帧信息的通道和PNG通道一样,有四个通道,与平常的RGB三通道不同,多了一个A通道,用于表示黑白灰通道。因此如果直接转换为jpg格式,多的一个A通道不知道如何处理。

3、压缩图片
其实就是改变图片尺寸大小。

im.thumbnail((128,128), Image.ANTIALIAS)

thumbnail方法就是生成指定尺寸的缩略图。其中(128,128)表示缩小后的尺寸,Image.ANTIALIAS表示图片的质量。这个方法和resize类似。

4、重新合成gif
处理完所有图片后,就需要将所有帧信息重新合成。

imglist[0].save(outf, 'gif', save_all=True, append_images=imglist[1:], loop=0, duration=dura)

这里使用的还是save方法,不过参数多了几个。通过设定save_all=True参数和 append_images,可以一次性将多帧图像同时存入GIF图片。还有一个duration参数控制的是帧率,我们可以直接从原图片中获取该信息。

dura = gif.info['duration']

除了帧率,gif.info返回的信息还有很多其他信息,

{'background': 0, 'extension': ('NETSCAPE2.0', 803), 'version': 'GIF89a', 'transparency': 23, 'duration': 60, 'loop': 0}

另外,loop参数也很重要,如果没设置这个参数会出现动图动一会儿就不动的情况。

这样,我们就把大的gif图片缩小了,效果如下。

大图展示:
python 2.7实现gif图片缩小_第1张图片

小图展示:
python 2.7实现gif图片缩小_第2张图片

你可能感兴趣的:(Python,gif压缩,PIL,pillow,python)