Merge pull request #5618 from radarhere/wal

Added WalImageFile class
This commit is contained in:
mergify[bot] 2021-08-06 13:29:19 +00:00 committed by GitHub
commit 545196c137
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 44 deletions

BIN
Tests/images/hopper_wal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -1,15 +1,21 @@
from PIL import WalImageFile from PIL import WalImageFile
from .helper import assert_image_equal_tofile
def test_open(): def test_open():
# Arrange # Arrange
TEST_FILE = "Tests/images/hopper.wal" TEST_FILE = "Tests/images/hopper.wal"
# Act # Act
im = WalImageFile.open(TEST_FILE) with WalImageFile.open(TEST_FILE) as im:
# Assert # Assert
assert im.format == "WAL" assert im.format == "WAL"
assert im.format_description == "Quake2 Texture" assert im.format_description == "Quake2 Texture"
assert im.mode == "P" assert im.mode == "P"
assert im.size == (128, 128) assert im.size == (128, 128)
assert isinstance(im, WalImageFile.WalImageFile)
assert_image_equal_tofile(im, "Tests/images/hopper_wal.png")

View File

@ -19,10 +19,12 @@ the default required length, also removing the need for the size parameter.
API Additions API Additions
============= =============
TODO Added WalImageFile class
^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
TODO :py:func:`PIL.WalImageFile.open()` previously returned a generic
:py:class:`PIL.Image.Image` instance. It now returns a dedicated
:py:class:`PIL.WalImageFile.WalImageFile` class.
Security Security
======== ========

View File

@ -23,12 +23,44 @@ and has been tested with a few sample files found using google.
To open a WAL file, use the :py:func:`PIL.WalImageFile.open()` function instead. To open a WAL file, use the :py:func:`PIL.WalImageFile.open()` function instead.
""" """
import builtins from . import Image, ImageFile
from . import Image
from ._binary import i32le as i32 from ._binary import i32le as i32
class WalImageFile(ImageFile.ImageFile):
format = "WAL"
format_description = "Quake2 Texture"
def _open(self):
self.mode = "P"
# read header fields
header = self.fp.read(32 + 24 + 32 + 12)
self._size = i32(header, 32), i32(header, 36)
Image._decompression_bomb_check(self.size)
# load pixel data
offset = i32(header, 40)
self.fp.seek(offset)
# strings are null-terminated
self.info["name"] = header[:32].split(b"\0", 1)[0]
next_name = header[56 : 56 + 32].split(b"\0", 1)[0]
if next_name:
self.info["next_name"] = next_name
def load(self):
if self.im:
# Already loaded
return
self.im = Image.core.new(self.mode, self.size)
self.frombytes(self.fp.read(self.size[0] * self.size[1]))
self.putpalette(quake2palette)
Image.Image.load(self)
def open(filename): def open(filename):
""" """
Load texture from a Quake2 WAL texture file. Load texture from a Quake2 WAL texture file.
@ -39,38 +71,7 @@ def open(filename):
:param filename: WAL file name, or an opened file handle. :param filename: WAL file name, or an opened file handle.
:returns: An image instance. :returns: An image instance.
""" """
# FIXME: modify to return a WalImageFile instance instead of return WalImageFile(filename)
# plain Image object ?
def imopen(fp):
# read header fields
header = fp.read(32 + 24 + 32 + 12)
size = i32(header, 32), i32(header, 36)
offset = i32(header, 40)
# load pixel data
fp.seek(offset)
Image._decompression_bomb_check(size)
im = Image.frombytes("P", size, fp.read(size[0] * size[1]))
im.putpalette(quake2palette)
im.format = "WAL"
im.format_description = "Quake2 Texture"
# strings are null-terminated
im.info["name"] = header[:32].split(b"\0", 1)[0]
next_name = header[56 : 56 + 32].split(b"\0", 1)[0]
if next_name:
im.info["next_name"] = next_name
return im
if hasattr(filename, "read"):
return imopen(filename)
else:
with builtins.open(filename, "rb") as fp:
return imopen(fp)
quake2palette = ( quake2palette = (