-
Notifications
You must be signed in to change notification settings - Fork 3
/
eTFT-gif-converter.py
executable file
·112 lines (88 loc) · 3.65 KB
/
eTFT-gif-converter.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
#!/usr/bin/env python
# VERSION 0.1 - eTFT screens - GIF Converter
# ALEX ARCE | alex.arce@pm.me - DEC.2020
import os, re, glob
import PIL
from PIL import Image
import subprocess
import argparse
# --------------------------------------------------------------------
class AnimationConverter:
def __init__(self, original_animation, animation_header):
self.gif = original_animation
self.anim_header = animation_header
def get_image_size_total(self, filename):
img = Image.open(filename)
total_size = img.width * img.height
img.close()
return total_size
def get_pixel_data(self, filename, file_descriptor):
img = Image.open(filename)
if img.mode in ('RGB', 'LA') or (img.mode == 'P' and 'transparency' in img.info):
pixels = list(img.convert('RGB').getdata())
pixels_len = len(pixels) - 1
for index, pix in enumerate(pixels):
rgb565 = (((pix[0] & 0xf8) << 8) + ((pix[1] & 0xfc) << 3) + (pix[2] >> 3))
if index == pixels_len:
file_descriptor.write('0x{:04X}'.format(rgb565))
else:
file_descriptor.write('0x{:04X}'.format(rgb565))
file_descriptor.write(',')
img.close()
def generate_frames(self):
# TODO - REsize gif here??
# ...
cmd = ['/usr/bin/convert', '-coalesce', self.gif, 'frame_%d.jpg']
subprocess.call(cmd, shell=False)
def get_frames_filelist(self):
filelist = glob.glob("*.jpg")
filelist.sort(key=lambda f: int(re.sub('\D', '', f)))
return filelist
def generate_header_file(self, filelist):
if len(filelist) > 0:
fd = open(self.anim_header, 'x')
fd.write("int frames = %d;\n" % len(filelist))
first_frame = filelist[0]
img = Image.open(first_frame)
fd.write("int animation_width = %d;\n" % img.width)
fd.write("int animation_height = %d;\n" % img.height)
img.close()
# const unsigned short PROGMEM animation[][6700]=
total_size = self.get_image_size_total(first_frame)
fd.write("const unsigned short PROGMEM animation[][%d] = {\n" % total_size)
current_block = 0
last_block = len(filelist)
for filename in filelist:
fd.write("{")
#fd.write("DATA_BLOCK_%d" % current_block)
self.get_pixel_data(filename, fd)
if current_block < last_block - 1:
fd.write("},\n")
else:
fd.write("}\n")
current_block = current_block + 1
fd.write("};")
fd.close()
return True
else:
return False
def Generate(self):
self.generate_frames()
frames = self.get_frames_filelist()
ret = self.generate_header_file(frames)
return ret
# --------------------------------------------------------------------
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--input', required=True)
parser.add_argument('-o', '--output', required=True)
args = parser.parse_args()
gif_file = args.input
header_file = args.output
# If header exists, delete it. Maybe we can change this behavior...
if os.path.exists(header_file):
os.remove(header_file)
converter = AnimationConverter(gif_file, header_file)
status = converter.Generate()
print("[+] Conversion result: %d" % status)
# --------------------------------------------------------------------