@@ -211,10 +211,8 @@ def _bitmap(self, header=0, offset=0):
211211 elif file_info ["compression" ] == self .RAW :
212212 if file_info ["bits" ] == 32 and header == 22 : # 32-bit .cur offset
213213 raw_mode , self .mode = "BGRA" , "RGBA"
214- elif file_info ["compression" ] == self .RLE8 :
215- decoder_name = "bmp_rle8"
216- elif file_info ["compression" ] == self .RLE4 :
217- decoder_name = "bmp_rle4"
214+ elif file_info ["compression" ] in (self .RLE8 , self .RLE4 ):
215+ decoder_name = "bmp_rle"
218216 else :
219217 raise OSError (f"Unsupported BMP compression ({ file_info ['compression' ]} )" )
220218
@@ -252,16 +250,18 @@ def _bitmap(self, header=0, offset=0):
252250
253251 # ---------------------------- Finally set the tile data for the plugin
254252 self .info ["compression" ] = file_info ["compression" ]
253+ args = [raw_mode ]
254+ if decoder_name == "bmp_rle" :
255+ args .append (file_info ["compression" ] == self .RLE4 )
256+ else :
257+ args .append (((file_info ["width" ] * file_info ["bits" ] + 31 ) >> 3 ) & (~ 3 ))
258+ args .append (file_info ["direction" ])
255259 self .tile = [
256260 (
257261 decoder_name ,
258262 (0 , 0 , file_info ["width" ], file_info ["height" ]),
259263 offset or self .fp .tell (),
260- (
261- raw_mode ,
262- ((file_info ["width" ] * file_info ["bits" ] + 31 ) >> 3 ) & (~ 3 ),
263- file_info ["direction" ],
264- ),
264+ tuple (args ),
265265 )
266266 ]
267267
@@ -278,10 +278,11 @@ def _open(self):
278278 self ._bitmap (offset = offset )
279279
280280
281- class BmpRle8Decoder (ImageFile .PyDecoder ):
281+ class BmpRleDecoder (ImageFile .PyDecoder ):
282282 _pulls_fd = True
283283
284284 def decode (self , buffer ):
285+ rle4 = self .args [1 ]
285286 data = bytearray ()
286287 x = 0
287288 while len (data ) < self .state .xsize * self .state .ysize :
@@ -295,67 +296,19 @@ def decode(self, buffer):
295296 if x + num_pixels > self .state .xsize :
296297 # Too much data for row
297298 num_pixels = max (0 , self .state .xsize - x )
298- data += byte * num_pixels
299- x += num_pixels
300- else :
301- if byte [0 ] == 0 :
302- # end of line
303- while len (data ) % self .state .xsize != 0 :
304- data += b"\x00 "
305- x = 0
306- elif byte [0 ] == 1 :
307- # end of bitmap
308- break
309- elif byte [0 ] == 2 :
310- # delta
311- bytes_read = self .fd .read (2 )
312- if len (bytes_read ) < 2 :
313- break
314- right , up = self .fd .read (2 )
315- data += b"\x00 " * (right + up * self .state .xsize )
316- x = len (data ) % self .state .xsize
299+ if rle4 :
300+ first_pixel = o8 (byte [0 ] >> 4 )
301+ second_pixel = o8 (byte [0 ] & 0x0F )
302+ for index in range (num_pixels ):
303+ if index % 2 == 0 :
304+ data += first_pixel
305+ else :
306+ data += second_pixel
317307 else :
318- # absolute mode
319- bytes_read = self .fd .read (byte [0 ])
320- data += bytes_read
321- if len (bytes_read ) < byte [0 ]:
322- break
323- x += byte [0 ]
324-
325- # align to 16-bit word boundary
326- if self .fd .tell () % 2 != 0 :
327- self .fd .seek (1 , os .SEEK_CUR )
328- rawmode = "L" if self .mode == "L" else "P"
329- self .set_as_raw (bytes (data ), (rawmode , 0 , self .args [- 1 ]))
330- return - 1 , 0
331-
332-
333- class BmpRle4Decoder (ImageFile .PyDecoder ):
334- _pulls_fd = True
335-
336- def decode (self , buffer ):
337- data = bytearray ()
338- x = 0
339- while len (data ) < self .state .xsize * self .state .ysize :
340- pixels = self .fd .read (1 )
341- byte = self .fd .read (1 )
342- if not pixels or not byte :
343- break
344- num_pixels = pixels [0 ]
345- if num_pixels :
346- # encoded mode
347- if x + num_pixels > self .state .xsize :
348- # Too much data for row
349- num_pixels = max (0 , self .state .xsize - x )
350- first_pixel = o8 (byte [0 ] >> 4 )
351- second_pixel = o8 (byte [0 ] & 0x0F )
352- for index in range (num_pixels ):
353- if index % 2 == 0 :
354- data += first_pixel
355- else :
356- data += second_pixel
308+ data += byte * num_pixels
357309 x += num_pixels
358310 else :
311+ # absolute mode
359312 if byte [0 ] == 0 :
360313 # end of line
361314 while len (data ) % self .state .xsize != 0 :
@@ -373,15 +326,18 @@ def decode(self, buffer):
373326 data += b"\x00 " * (right + up * self .state .xsize )
374327 x = len (data ) % self .state .xsize
375328 else :
376- # absolute mode (2 pixels per byte)
377- total_bytes_to_read = byte [0 ] // 2
378- bytes_read = self .fd .read (total_bytes_to_read )
379- for byte_read in bytes_read :
380- first_pixel = o8 (byte_read >> 4 )
381- data += first_pixel
382- second_pixel = o8 (byte_read & 0x0F )
383- data += second_pixel
384- if len (bytes_read ) < total_bytes_to_read :
329+ if rle4 :
330+ # 2 pixels per byte
331+ byte_count = byte [0 ] // 2
332+ bytes_read = self .fd .read (byte_count )
333+ for byte_read in bytes_read :
334+ data += o8 (byte_read >> 4 )
335+ data += o8 (byte_read & 0x0F )
336+ else :
337+ byte_count = byte [0 ]
338+ bytes_read = self .fd .read (byte_count )
339+ data += bytes_read
340+ if len (bytes_read ) < byte_count :
385341 break
386342 x += byte [0 ]
387343
@@ -498,8 +454,7 @@ def _save(im, fp, filename, bitmap_header=True):
498454
499455Image .register_mime (BmpImageFile .format , "image/bmp" )
500456
501- Image .register_decoder ("bmp_rle8" , BmpRle8Decoder )
502- Image .register_decoder ("bmp_rle4" , BmpRle4Decoder )
457+ Image .register_decoder ("bmp_rle" , BmpRleDecoder )
503458
504459Image .register_open (DibImageFile .format , DibImageFile , _dib_accept )
505460Image .register_save (DibImageFile .format , _dib_save )
0 commit comments