forked from OpenDUNE/OpenDUNE
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsave_pictures.py
135 lines (128 loc) · 5.13 KB
/
save_pictures.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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#!/usr/bin/env python
# vim: tabstop=4 shiftwidth=4 softtabstop=4 noexpandtab
#
from struct import pack
def split_string(s, n):
return [s[i*n:i*n+n] for i, j in enumerate(s[::n])]
def save_pbm(filename, width, height, pixels, palette):
save_iff(filename, width, height, pixels, palette, 'PBM ', 8)
def save_ilbm(filename, width, height, pixels, palette):
bpp = 8 * len(pixels) / (width * height)
save_iff(filename, width, height, pixels, palette, 'ILBM', bpp)
def save_iff(filename, width, height, pixels, palette, fmt, bpp):
if (width & 1) != 0:
pixels = ''.join([line + chr(0) for line in split_string(pixels, width)])
with open(filename, 'wb') as pbm_file:
# width, height, x, y, bitplanes, mask, compression, pad, transp_col, ratio_x, ratio_y, screen width, screen height
bmhd_chunk = 'BMHD' + pack('>LHHHHBBBBHBBHH', 20, width, height, 0, 0, bpp, 2, 0, 0, 0, 10, 10, width, height);
cmap_chunk = '' if not palette else 'CMAP' + pack('>L', len(palette)) + palette
body_chunk = 'BODY' + pack('>L', len(pixels)) + pixels
size = 4 + len(body_chunk) + len(bmhd_chunk) + len(cmap_chunk)
form = 'FORM' + pack('>L', size) + fmt + bmhd_chunk + cmap_chunk + body_chunk
pbm_file.write(form)
print filename, "written", bpp, "bpp"
def save_flc(filename, width, height, frames, palette):
with open(filename, 'wb') as flc_file:
frame_delay = 100 # ms per frame
# 1st frame
flc_frames = []
if palette is None:
palette_sub_chunk = None
else:
# sub_chunk_size, sub_chunk_type
# packet_count, skip, count (count = 0 for 256)
palette_sub_chunk = pack('<LHHBB', len(palette) + 6 + 2 + 2, 0x04, 1, 0, (len(palette) / 3) & 0xff)
palette_sub_chunk += palette
# Full frame RLE : 0x0f
encoded_frame = ''
for y in range(height):
packets = []
x = 1
count = 1
repeat = True
#print frames[0][y*width:(y+1)*width].encode('hex')
while x < width:
#print x, y, repeat
if repeat:
if frames[0][y*width+(x-1)] == frames[0][y*width+x] and count < 127:
count += 1
elif count > 2:
packets.append(chr(count)+frames[0][y*width+(x-1)])
count = 1
else:
repeat = False
count += 1
else:
if frames[0][y*width+(x-2)] == frames[0][y*width+(x-1)] == frames[0][y*width+x]:
packets.append(pack('<b', 2-count)+frames[0][y*width+x-count:y*width+x-2])
repeat = True
count = 3
elif count >= 128: # To be checked
packets.append(pack('<b', 1-count)+frames[0][y*width+x-count:y*width+x-1])
count = 2
else:
count += 1
x += 1
if count > 0:
if repeat:
packets.append(chr(count)+frames[0][y*width+(x-1)])
else:
packets.append(pack('<b', -count)+frames[0][y*width+x-count:y*width+x])
#print count, map(lambda s : s.encode('hex'), packets)
encoded_frame += pack('<B', len(packets)) + ''.join(packets)
full_frame_rle_sub_chunk = pack('<LH', len(encoded_frame) + 6, 0x0f) + encoded_frame
if palette_sub_chunk is None:
first_frame = pack('<LHHHHHH', len(full_frame_rle_sub_chunk) + 16, 0xf1fa, 1, 0, 0, 0, 0)
else:
first_frame = pack('<LHHHHHH', len(full_frame_rle_sub_chunk) + len(palette_sub_chunk) + 16, 0xf1fa, 2, 0, 0, 0, 0)
first_frame += palette_sub_chunk
first_frame += full_frame_rle_sub_chunk
flc_frames = [first_frame]
for frame in range(1, len(frames)):
encoded_frame = ''
equals_lines = 0
line_count = 0
for y in range(height):
current_line = frames[frame][y*width:(y+1)*width]
previous_line = frames[frame-1][y*width:(y+1)*width]
if current_line == previous_line:
equals_lines += 1
else:
if (equals_lines > 0):
encoded_frame += pack('<h', -equals_lines)
equals_lines = 0
packets = []
# no compression test:
#if width > 254:
# packets.append(pack('<Bb', 0, 127) + frames[frame][y*width:y*width+254])
# packets.append(pack('<Bb', 0, (width/2)-127) + frames[frame][y*width+254:(y+1)*width])
#else:
# packets.append(pack('<Bb', 0, (width/2)) + frames[frame][y*width:(y+1)*width])
x = 0
while x < width:
skip = 0
count = 0
while x < width and skip < 254 and current_line[x:x+2] == previous_line[x:x+2]:
x += 2
skip += 2
rle = True
while x < width and count < 127 and current_line[x:x+2] != previous_line[x:x+2]:
if rle and count > 0 and current_line[x:x+2] != current_line[x-2:x]:
rle = False
x += 2
count += 1
if rle and count > 1:
packets.append(pack('<Bb', skip, -count) + current_line[x-2:x])
else:
packets.append(pack('<Bb', skip, count) + current_line[x-count*2:x])
encoded_frame += pack('<H', len(packets)) + ''.join(packets)
line_count += 1
# frame with 1 sub chunk of type 7 (DELTA_FLC)
flc_frames.append(pack('<LHHHHHHLHH', len(encoded_frame) + 24, 0xf1fa, 1, 0, 0, 0, 0, len(encoded_frame) + 8, 0x07, line_count) + encoded_frame)
flc_data = ''.join(flc_frames)
# 0xAF12 is signature for FLC files
flc_header = pack('<LHHHHHHL', len(flc_data) + 128, 0xAF12, len(flc_frames), width, height, 8, 0, frame_delay)
flc_header += chr(0) * (128 - len(flc_header))
flc_file.write(flc_header)
flc_file.write(flc_data)
print filename, "written"