@@ -177,7 +177,7 @@ def read_palette(self, palette=None):
177
177
return palette
178
178
179
179
def read_data (self , buffer = None ):
180
- line_size = self .width >> 1
180
+ line_size = ( self .width + 1 ) >> 1
181
181
if buffer is None :
182
182
buffer = bytearray (line_size * self .height )
183
183
@@ -207,17 +207,23 @@ def read_header(self):
207
207
) = struct .unpack (">I4sIIBBBBB4s" , f .read (25 ))
208
208
assert size == 13 # header length
209
209
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 :
211
211
raise ValueError ("16-color non-interaced PNG expected" )
212
212
213
213
def read_palette (self , palette = None ):
214
214
if palette is None :
215
215
palette = array .array ('H' , (0 for i in range (16 )))
216
216
with open (self .filename , 'rb' ) as f :
217
217
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 ):
221
227
c = color565 (* struct .unpack ("BBB" , f .read (3 )))
222
228
palette [color ] = ((c << 8 ) | (c >> 8 )) & 0xffff
223
229
return palette
@@ -236,14 +242,30 @@ def read_data(self, buffer=None):
236
242
data .extend (f .read (size ))
237
243
f .seek (4 , 1 ) # skip CRC
238
244
data = zlib .decompress (data )
239
- line_size = self .width >> 1
245
+ line_size = ( self .width + 1 ) >> 1
240
246
if buffer is None :
241
247
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
247
269
return buffer
248
270
249
271
0 commit comments