8000 Support also 8-bit PNG images in Stage · python-ugame/circuitpython-stage@f993d5f · GitHub
[go: up one dir, main page]

Skip to content

Commit f993d5f

Browse files
committed
Support also 8-bit PNG images in Stage
As long as only 16 colors are used
1 parent 9c88283 commit f993d5f

File tree

1 file changed

+33
-11
lines changed

1 file changed

+33
-11
lines changed

stage.py

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ def read_palette(self, palette=None):
177177
return palette
178178

179179
def read_data(self, buffer=None):
180-
line_size = self.width >> 1
180+
line_size = (self.width + 1 ) >> 1
181181
if buffer is None:
182182
buffer = bytearray(line_size * self.height)
183183

@@ -207,17 +207,23 @@ def read_header(self):
207207
) = struct.unpack(">I4sIIBBBBB4s", f.read(25))
208208
assert size == 13 # header length
209209
assert chunk == b'IHDR'
210-
if self.depth != 4 or self.mode != 3 or self.interlaced != 0:
210+
if self.depth not in {4, 8} or self.mode != 3 or self.interlaced != 0:
211211
raise ValueError("16-color non-interaced PNG expected")
212212

213213
def read_palette(self, palette=None):
214214
if palette is None:
215215
palette = array.array('H', (0 for i in range(16)))
216216
with open(self.filename, 'rb') as f:
217217
f.seek(8 + 25)
218-
size, chunk = 10000 struct.unpack(">I4s", f.read(8))
219-
assert chunk == b'PLTE'
220-
for color in range(size // 3):
218+
while True:
219+
size, chunk = struct.unpack(">I4s", f.read(8))
220+
if chunk == b'PLTE':
221+
break
222+
f.seek(size + 4, 1)
223+
colors = size // 3
224+
if colors > 16:
225+
raise ValueError("16-color PNG expected")
226+
for color in range(colors):
221227
c = color565(*struct.unpack("BBB", f.read(3)))
222228
palette[color] = ((c << 8) | (c >> 8)) & 0xffff
223229
return palette
@@ -236,14 +242,30 @@ def read_data(self, buffer=None):
236242
data.extend(f.read(size))
237243
f.seek(4, 1) # skip CRC
238244
data = zlib.decompress(data)
239-
line_size = self.width >> 1
245+
line_size = (self.width + 1) >> 1
240246
if buffer is None:
241247
buffer = bytearray(line_size * self.height)
242-
for line in range(self.height):
243-
a = line * line_size
244-
b = line * (line_size + 1)
245-
assert data[b] == 0 # no filter
246-
buffer[a:a + line_size] = data[b + 1:b + 1 + line_size]
248+
if self.depth == 4:
249+
for line in range(self.height):
250+
a = line * line_size
251+
b = line * (line_size + 1)
252+
assert data[b] == 0 # no filter
253+
buffer[a:a + line_size] = data[b + 1:b + 1 + line_size]
254+
elif self.depth == 8:
255+
for line in range(self.height):
256+
a = line * line_size
257+
b = line * (self.width + 1)
258+
assert data[b] == 0 # no filter
259+
b += 1
260+
for col in range(line_size):
261+
buffer[a] = (data[b] & 0x0f) << 4
262+
b += 1
263+
try:
264+
buffer[a] |= data[b] & 0x0f
265+
except IndexError:
266+
pass
267+
b += 1
268+
a += 1
247269
return buffer
248270

249271

0 commit comments

Comments
 (0)
0