mirror of
https://github.com/python-pillow/Pillow.git
synced 2024-12-26 01:46:18 +03:00
Added BMP RLE8 decoder
This commit is contained in:
parent
397a940995
commit
0ace3fcd26
BIN
Tests/images/hopper_rle8.bmp
Normal file
BIN
Tests/images/hopper_rle8.bmp
Normal file
Binary file not shown.
After Width: | Height: | Size: 26 KiB |
|
@ -4,7 +4,12 @@ import pytest
|
|||
|
||||
from PIL import BmpImagePlugin, Image
|
||||
|
||||
from .helper import assert_image_equal, assert_image_equal_tofile, hopper
|
||||
from .helper import (
|
||||
assert_image_equal,
|
||||
assert_image_equal_tofile,
|
||||
assert_image_similar_tofile,
|
||||
hopper,
|
||||
)
|
||||
|
||||
|
||||
def test_sanity(tmp_path):
|
||||
|
@ -125,6 +130,11 @@ def test_rgba_bitfields():
|
|||
assert_image_equal_tofile(im, "Tests/images/bmp/q/rgb32bf-xbgr.bmp")
|
||||
|
||||
|
||||
def test_rle8():
|
||||
with Image.open("Tests/images/hopper_rle8.bmp") as im:
|
||||
assert_image_similar_tofile(im.convert("RGB"), "Tests/images/hopper.bmp", 12)
|
||||
|
||||
|
||||
def test_offset():
|
||||
# This image has been hexedited
|
||||
# to exclude the palette size from the pixel data offset
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
#
|
||||
|
||||
|
||||
import os
|
||||
|
||||
from . import Image, ImageFile, ImagePalette
|
||||
from ._binary import i16le as i16
|
||||
from ._binary import i32le as i32
|
||||
|
@ -167,6 +169,7 @@ class BmpImageFile(ImageFile.ImageFile):
|
|||
raise OSError(f"Unsupported BMP pixel depth ({file_info['bits']})")
|
||||
|
||||
# ---------------- Process BMP with Bitfields compression (not palette)
|
||||
decoder_name = "raw"
|
||||
if file_info["compression"] == self.BITFIELDS:
|
||||
SUPPORTED = {
|
||||
32: [
|
||||
|
@ -208,6 +211,8 @@ class BmpImageFile(ImageFile.ImageFile):
|
|||
elif file_info["compression"] == self.RAW:
|
||||
if file_info["bits"] == 32 and header == 22: # 32-bit .cur offset
|
||||
raw_mode, self.mode = "BGRA", "RGBA"
|
||||
elif file_info["compression"] == self.RLE8:
|
||||
decoder_name = "bmp_rle"
|
||||
else:
|
||||
raise OSError(f"Unsupported BMP compression ({file_info['compression']})")
|
||||
|
||||
|
@ -247,7 +252,7 @@ class BmpImageFile(ImageFile.ImageFile):
|
|||
self.info["compression"] = file_info["compression"]
|
||||
self.tile = [
|
||||
(
|
||||
"raw",
|
||||
decoder_name,
|
||||
(0, 0, file_info["width"], file_info["height"]),
|
||||
offset or self.fp.tell(),
|
||||
(
|
||||
|
@ -271,6 +276,40 @@ class BmpImageFile(ImageFile.ImageFile):
|
|||
self._bitmap(offset=offset)
|
||||
|
||||
|
||||
class BmpRleDecoder(ImageFile.PyDecoder):
|
||||
_pulls_fd = True
|
||||
|
||||
def decode(self, buffer):
|
||||
data = bytearray()
|
||||
while True:
|
||||
num_pixels = self.fd.read(1)[0]
|
||||
byte = self.fd.read(1)
|
||||
if num_pixels:
|
||||
# encoded mode
|
||||
data += byte * num_pixels
|
||||
else:
|
||||
if byte[0] == 0:
|
||||
# end of line
|
||||
while len(data) % self.state.xsize != 0:
|
||||
data += b"\x00"
|
||||
elif byte[0] == 1:
|
||||
# end of bitmap
|
||||
break
|
||||
elif byte[0] == 2:
|
||||
# delta
|
||||
right, up = self.fd.read(2)
|
||||
data += b"\x00" * (right + up * self.state.xsize)
|
||||
else:
|
||||
# absolute mode
|
||||
data += self.fd.read(byte[0])
|
||||
|
||||
# align to 16-bit word boundary
|
||||
if self.fd.tell() % 2 != 0:
|
||||
self.fd.seek(1, os.SEEK_CUR)
|
||||
self.set_as_raw(bytes(data), ("P", 0, self.args[-1]))
|
||||
return -1, 0
|
||||
|
||||
|
||||
# =============================================================================
|
||||
# Image plugin for the DIB format (BMP alias)
|
||||
# =============================================================================
|
||||
|
@ -372,6 +411,8 @@ Image.register_extension(BmpImageFile.format, ".bmp")
|
|||
|
||||
Image.register_mime(BmpImageFile.format, "image/bmp")
|
||||
|
||||
Image.register_decoder("bmp_rle", BmpRleDecoder)
|
||||
|
||||
Image.register_open(DibImageFile.format, DibImageFile, _dib_accept)
|
||||
Image.register_save(DibImageFile.format, _dib_save)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user