Added BLP1 saving

This commit is contained in:
Andrew Murray 2022-02-25 23:58:13 +11:00
parent 1859bc3462
commit e36774617c
3 changed files with 34 additions and 20 deletions

View File

@ -31,16 +31,18 @@ def test_load_blp2_dxt1a():
def test_save(tmp_path): def test_save(tmp_path):
im = hopper("P")
f = str(tmp_path / "temp.blp") f = str(tmp_path / "temp.blp")
im.save(f)
for version in ("BLP1", "BLP2"):
im = hopper("P")
im.save(f, blp_version=version)
with Image.open(f) as reloaded: with Image.open(f) as reloaded:
assert_image_equal(im.convert("RGB"), reloaded) assert_image_equal(im.convert("RGB"), reloaded)
with Image.open("Tests/images/transparent.png") as im: with Image.open("Tests/images/transparent.png") as im:
f = str(tmp_path / "temp.blp") f = str(tmp_path / "temp.blp")
im.convert("P").save(f) im.convert("P").save(f, blp_version=version)
with Image.open(f) as reloaded: with Image.open(f) as reloaded:
assert_image_similar(im, reloaded, 8) assert_image_similar(im, reloaded, 8)

View File

@ -26,6 +26,20 @@ Fully supported formats
.. contents:: .. contents::
BLP
^^^
BLP is the Blizzard Mipmap Format, a texture format used in World of
Warcraft. Pillow supports reading ``JPEG`` Compressed or raw ``BLP1``
images, and all types of ``BLP2`` images.
Pillow supports writing BLP images. The :py:meth:`~PIL.Image.Image.save` method
can take the following keyword arguments:
**blp_version**
If present and set to "BLP1", images will be saved as BLP1. Otherwise, images
will be saved as BLP2.
BMP BMP
^^^ ^^^
@ -1042,13 +1056,6 @@ Pillow reads and writes X bitmap files (mode ``1``).
Read-only formats Read-only formats
----------------- -----------------
BLP
^^^
BLP is the Blizzard Mipmap Format, a texture format used in World of
Warcraft. Pillow supports reading ``JPEG`` Compressed or raw ``BLP1``
images, and all types of ``BLP2`` images.
CUR CUR
^^^ ^^^

View File

@ -439,7 +439,7 @@ class BLP2Decoder(_BLPBaseDecoder):
self.set_as_raw(bytes(data)) self.set_as_raw(bytes(data))
class BLP2Encoder(ImageFile.PyEncoder): class BLPEncoder(ImageFile.PyEncoder):
_pushes_fd = True _pushes_fd = True
def _write_palette(self): def _write_palette(self):
@ -472,15 +472,20 @@ def _save(im, fp, filename, save_all=False):
if im.mode != "P": if im.mode != "P":
raise ValueError("Unsupported BLP image mode") raise ValueError("Unsupported BLP image mode")
fp.write(b"BLP2") magic = b"BLP1" if im.encoderinfo.get("blp_version") == "BLP1" else b"BLP2"
fp.write(magic)
fp.write(struct.pack("<i", 1)) # Uncompressed or DirectX compression fp.write(struct.pack("<i", 1)) # Uncompressed or DirectX compression
fp.write(struct.pack("<b", Encoding.UNCOMPRESSED)) fp.write(struct.pack("<b", Encoding.UNCOMPRESSED))
fp.write(struct.pack("<b", 1 if im.palette.mode == "RGBA" else 0)) fp.write(struct.pack("<b", 1 if im.palette.mode == "RGBA" else 0))
fp.write(struct.pack("<b", 0)) # alpha encoding fp.write(struct.pack("<b", 0)) # alpha encoding
fp.write(struct.pack("<b", 0)) # mips fp.write(struct.pack("<b", 0)) # mips
fp.write(struct.pack("<II", *im.size)) fp.write(struct.pack("<II", *im.size))
if magic == b"BLP1":
fp.write(struct.pack("<i", 5))
fp.write(struct.pack("<i", 0))
ImageFile._save(im, fp, [("BLP2", (0, 0) + im.size, 0, im.mode)]) ImageFile._save(im, fp, [("BLP", (0, 0) + im.size, 0, im.mode)])
Image.register_open(BlpImageFile.format, BlpImageFile, _accept) Image.register_open(BlpImageFile.format, BlpImageFile, _accept)
@ -489,4 +494,4 @@ Image.register_decoder("BLP1", BLP1Decoder)
Image.register_decoder("BLP2", BLP2Decoder) Image.register_decoder("BLP2", BLP2Decoder)
Image.register_save(BlpImageFile.format, _save) Image.register_save(BlpImageFile.format, _save)
Image.register_encoder("BLP2", BLP2Encoder) Image.register_encoder("BLP", BLPEncoder)