使用PIL库进行gif图的解析或合成

那个星夜越过千年
而我绕过半个地球
重新来寻那个你
那个亮尽我的眼的你
一颗流星划过
坠入无边黑暗
你等我一千年
我找你十万里
——《星空》湮夫

跨界艺术家插画师James R. Eads的画作,似乎一下子游离到了另一个世界。在他的笔下,一个个创思化身成一个个闪光的光点,五彩缤纷,随意萦绕,勾勒出一个个美轮美奂的画境,似有阳光的热烈,也有月光的浪漫,更有浩瀚星光似的唯美与空明,让人很容易就沉浸在这美妙的小宇宙中。

受梵高的绘画风格影响,他巧妙地将色彩与富有动感的笔触结合起来,使画面梦幻而富有冲击力。神秘缤纷的色彩、浩瀚如宇宙的笔触,自然与人就这样被James R. Eads用独特的绘画方法结合在一起,启发著人们去思考人与人、人与自然之间的关系。

欣赏作品:








我们尝试利用PIL库将gif图进行解析, 然后再重新合成gif图, 并改变帧的变化速率。

解析gif图代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#-*- coding: UTF-8 -*-  

import os
from PIL import Image

def analyseImage(path):
'''
Pre-process pass over the image to determine the mode (full or additive).
Necessary as assessing single frames isn't reliable. Need to know the mode
before processing all frames.
'''
im = Image.open(path)
results = {
'size': im.size,
'mode': 'full',
}
try:
while True:
if im.tile:
tile = im.tile[0]
update_region = tile[1]
update_region_dimensions = update_region[2:]
if update_region_dimensions != im.size:
results['mode'] = 'partial'
break
im.seek(im.tell() + 1)
except EOFError:
pass
return results


def processImage(path):
'''
Iterate the GIF, extracting each frame.
'''
mode = analyseImage(path)['mode']

im = Image.open(path)

i = 0
p = im.getpalette()
last_frame = im.convert('RGBA')

try:
while True:
print ("saving %s (%s) frame %d, %s %s" % (path, mode, i, im.size, im.tile))

'''
If the GIF uses local colour tables, each frame will have its own palette.
If not, we need to apply the global palette to the new frame.
'''
if not im.getpalette():
im.putpalette(p)

new_frame = Image.new('RGBA', im.size)

'''
Is this file a "partial"-mode GIF where frames update a region of a different size to the entire image?
If so, we need to construct the new frame by pasting it on top of the preceding frames.
'''
if mode == 'partial':
new_frame.paste(last_frame)

new_frame.paste(im, (0,0), im.convert('RGBA'))
new_frame.save('%s-%d.png' % (''.join(os.path.basename(path).split('.')[:-1]), i), 'PNG')

i += 1
last_frame = new_frame
im.seek(im.tell() + 1)
except EOFError:
pass



def main():
processImage('1.gif')


if __name__ == "__main__":
main()

合成gif图代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#-*- coding: UTF-8 -*-  

import imageio

def create_gif(image_list, gif_name):

frames = []
for image_name in image_list:
frames.append(imageio.imread(image_name))
# Save them as frames into a gif
imageio.mimsave(gif_name, frames, 'GIF', duration = 0.1)

return

def main():
image_list = ['1-0.png', '1-2.png', '1-4.png',
'1-6.png', '1-8.png', '1-10.png']
gif_name = 'created_gif1.gif'
create_gif(image_list, gif_name)

if __name__ == "__main__":
main()

某gif图解析后部分图片如下:



gif图合成后:


Donate? comment?