@@ -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 = 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