-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgif.py
115 lines (108 loc) · 5.57 KB
/
gif.py
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/env python3
'''
test the gif file structure
'''
import math
import argparse
from PIL import Image
from src import logical_screen_description_block, global_color_table, local_color_table, image_descriptor
from src import plain_text_extension, application_extension, graphic_control_extension, comment_extension
from src import bytes_to_int
from src import Decoder
from src import BEGIN, END, EXTENTION_INTRODUCER
class Reader:
'''
read the gif file
'''
def __init__(self, file_name):
self._data = open(file_name, "rb").read()
self._begin = 0
self._picture_index = 0
def read_until(self, end_value):
while True:
if self._data[self._begin] == end_value:
break
self._begin += 1
def header_assert(self):
'''
assert the file is the gif file
'''
assert(self._data[0] == ord("G"))
assert(self._data[1] == ord("I"))
assert(self._data[2] == ord("F"))
self._version = self._data[3:6].decode("utf-8")
def save_pictures(self, width, height, decode_result, picture_name):
'''
save the decoded .gif static data to the .jpg data.
'''
background_color_index = self._logical_screen_description_block.background_color_index
img = Image.new("RGB", (width, height), self._global_color_table.rgb_list[background_color_index])
pixels = img.load()
for i in range(width):
for j in range(height):
if self._image_descriptor.local_color_table_flag:
pixels[i, j] = self._local_color_table.rgb_list[decode_result[width*i+j]]
else:
pixels[i, j] = self._global_color_table.rgb_list[decode_result[width*i+j]]
img.save(picture_name)
def start(self):
'''
begin to parse the gif picture.
'''
self.header_assert()
self._logical_screen_description_block = logical_screen_description_block(self._data)
self._global_color_table_bytes_size = 3 * 2**(self._logical_screen_description_block.global_color_table_size+1)
self._global_color_table_data = self._data[13:13+self._global_color_table_bytes_size]
self._global_color_table = global_color_table(self._global_color_table_data, self._global_color_table_bytes_size)
self._begin = 13 + self._global_color_table_bytes_size
if self._version == "89a":
while True:
if self._data[self._begin] == EXTENTION_INTRODUCER:
self._begin += 1
if self._data[self._begin] == 0xff:
self._application_extension = application_extension(self._data, self._begin)
self._begin += 18 # add one \x0 end
elif self._data[self._begin] == 0xf9:
self._graphic_control_extension = graphic_control_extension(self._data, self._begin)
self._begin += 7 # add one \x0 end
elif self._data[self._begin] == 0x01:
self._plain_text_extension = plain_text_extension(self._data, self._begin)
self._begin = self._plain_text_extension.current
elif self._data[self._begin] == 0xfe:
self._comment_comment_extension = comment_extension(self._data, self._begin)
self._begin = self._comment_comment_extension.current
elif self._data[self._begin] == BEGIN:
self._begin += 1
self._image_descriptor = image_descriptor(self._data, self._begin)
self._begin += 9
if self._image_descriptor.local_color_table_flag:
self._local_color_table_bytes_size = 3 * 2**(self._image_descriptor.size_of_local_color_table+1)
self._local_color_table_data = self._data[self._begin:self._begin+self._local_color_table_bytes_size]
self._local_color_table = local_color_table(self._local_color_table_data, self._local_color_table_bytes_size)
self._begin += local_color_table_bytes_size
elif self._data[self._begin] == END:
break
else:
blocks_data = b""
lzw_minium_size = self._data[self._begin]
self._begin += 1
while True:
block_size = self._data[self._begin]
if block_size == 0:
break
sub_blocks_data = self._data[self._begin+1:self._begin+block_size+1]
blocks_data += sub_blocks_data
self._begin += block_size + 1
self._begin += 1
decoder = Decoder(lzw_minium_size, blocks_data[::-1])
decoder.start()
decode_result = decoder.get_result()
assert(len(decode_result) == self._image_descriptor.get_size())
self.save_pictures(self._image_descriptor.image_width, self._image_descriptor.image_height, decode_result, "output_{}.jpg".format(self._picture_index))
self._picture_index += 1
if __name__ == "__main__":
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument("-i", "--input", help="enter the input file path")
args = arg_parser.parse_args()
reader = Reader(args.input)
reader.start()