Skip to content

Commit

Permalink
Added BLP1 saving
Browse files Browse the repository at this point in the history
  • Loading branch information
radarhere committed Feb 25, 2022
1 parent 1859bc3 commit e367746
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 20 deletions.
20 changes: 11 additions & 9 deletions Tests/test_file_blp.py
Expand Up @@ -31,19 +31,21 @@ def test_load_blp2_dxt1a():


def test_save(tmp_path):
im = hopper("P")
f = str(tmp_path / "temp.blp")
im.save(f)

with Image.open(f) as reloaded:
assert_image_equal(im.convert("RGB"), reloaded)

with Image.open("Tests/images/transparent.png") as im:
f = str(tmp_path / "temp.blp")
im.convert("P").save(f)
for version in ("BLP1", "BLP2"):
im = hopper("P")
im.save(f, blp_version=version)

with Image.open(f) as reloaded:
assert_image_similar(im, reloaded, 8)
assert_image_equal(im.convert("RGB"), reloaded)

with Image.open("Tests/images/transparent.png") as im:
f = str(tmp_path / "temp.blp")
im.convert("P").save(f, blp_version=version)

with Image.open(f) as reloaded:
assert_image_similar(im, reloaded, 8)

im = hopper()
with pytest.raises(ValueError):
Expand Down
21 changes: 14 additions & 7 deletions docs/handbook/image-file-formats.rst
Expand Up @@ -26,6 +26,20 @@ Fully supported formats

.. 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
^^^

Expand Down Expand Up @@ -1042,13 +1056,6 @@ Pillow reads and writes X bitmap files (mode ``1``).
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
^^^

Expand Down
13 changes: 9 additions & 4 deletions src/PIL/BlpImagePlugin.py
Expand Up @@ -439,7 +439,7 @@ def _load(self):
self.set_as_raw(bytes(data))


class BLP2Encoder(ImageFile.PyEncoder):
class BLPEncoder(ImageFile.PyEncoder):
_pushes_fd = True

def _write_palette(self):
Expand Down Expand Up @@ -472,15 +472,20 @@ def _save(im, fp, filename, save_all=False):
if im.mode != "P":
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("<b", Encoding.UNCOMPRESSED))
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)) # mips
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)
Expand All @@ -489,4 +494,4 @@ def _save(im, fp, filename, save_all=False):
Image.register_decoder("BLP2", BLP2Decoder)

Image.register_save(BlpImageFile.format, _save)
Image.register_encoder("BLP2", BLP2Encoder)
Image.register_encoder("BLP", BLPEncoder)

0 comments on commit e367746

Please sign in to comment.