-
Notifications
You must be signed in to change notification settings - Fork 4
/
dutils.py
144 lines (129 loc) · 3.37 KB
/
dutils.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
136
137
138
139
140
141
142
import struct
from StringIO import StringIO
def read32(f, le=False):
x = f.read(4)
if le:
return struct.unpack("<I", x)[0]
else:
return struct.unpack(">I", x)[0]
def read16(f, signed=False):
x = f.read(2)
if signed:
return struct.unpack(">h", x)[0]
else:
return struct.unpack(">H", x)[0]
def read8(f):
x = f.read(1)
return struct.unpack("<B", x)[0]
def readString(f):
s = read8(f)
return f.read(s)
def getString(s):
if len(s) == 0:
return s
l = ord(s[0])
if l == 0:
assert len(s) == 1
return ""
s = s[1:]
if s[-1] == '\x00':
s = s[:-1]
assert l == len(s)
return s
class Rect:
def width(self):
return self.right - self.left
def height(self):
return self.bottom - self.top
def __str__(self):
return "(%d, %d, %d, %d)" % (self.left, self.top, self.right, self.bottom)
def readRect(f):
r = Rect()
r.top = read16(f,True)
r.left = read16(f,True)
r.bottom = read16(f,True)
r.right = read16(f,True)
return r
def unPackBits(data):
output = ""
pos = 0
while pos < len(data):
n = ord(data[pos])
pos = pos + 1
if n < 0x80:
# literal run
output = output + data[pos:pos+n+1]
pos = pos + n + 1
elif n > 0x80:
# run length
output = output + data[pos] * (0x100 - n + 1)
pos = pos + 1
else:
# no-op
pass
return output
def getPaletteFor(pos, movie):
palentries = 256
palette = ""
palId = 0
for n in range(pos+1):
if movie.frames[n].palette != 0:
palId = movie.frames[n].palette
if palId != 0 and 'CLUT' in movie.resources:
for p in movie.resources['CLUT']:
if p.rid == palId + 1024:
p.seek(0)
d = p.read()
for i in range(len(d)/6):
l = len(d)/6
n = i
if not movie.mac:
n = l - i - 1
if i >= palentries:
break
palette = palette + d[n*6+4] + d[n*6+2] + d[n*6] + '\x00'
while len(palette) < 4*palentries:
palette = palette + '\x00'
else:
pf = open("data/mac.pal")
pf.read(6) # 0:seed,4:flags
assert read16(pf)+1 == 256 # count
pf = pf.read()
n = 0
for e in range(palentries):
ee = 255 - e
# high bytes of uint16s, ignore the first
# palette = palette + pf[e*8+6] + pf[e*8+4] + pf[e*8+2] + '\x00'
palette = palette + pf[ee*8+6] + pf[ee*8+4] + pf[ee*8+2] + '\x00'
return palette
import struct
def imageFromDIB(data, palette):
# fake a stupid BMP (sigh)
assert ord(data[0]) == 40 and ord(data[1]) == 0 # size
depth = ord(data[14])
width, height = struct.unpack("<Ii", data[4:12])
assert depth == 1 or depth == 4 or depth == 8
palentries = ord(data[32]) + (ord(data[33]) << 8)
if palentries == 0:
# palentries = 2**depth
palentries = 256
else:
# FIXME
print "WARNING: palentries %d" % palentries
totalsize = 14 + len(data) + len(palette)
offset = 14 + 40 + len(palette)
rawdata = data[40:]
if depth == 1:
# 1bpp handled differently: always top-down
if height > 0:
data = data[:8] + struct.pack("<i", -height) + data[12:]
# 1bpp handled differently: word padding, so we have to expand to dword padding
oldrawdata = rawdata
rawdata = bytearray()
realwidth = ((width+7)/8)
realwidth = ((realwidth+1)/2)*2
neededwidth = ((realwidth+3)/4)*4
for n in range(height):
rawdata.extend(bytearray(oldrawdata[n*realwidth:n*realwidth+realwidth] + '\x00' * (neededwidth - realwidth)))
dibdata = "BM" + struct.pack("<III", totalsize, 0, offset) + data[:40] + palette + rawdata
return str(dibdata)