Skip to content

Commit

Permalink
Merge pull request #26 from sketchfab/feature/updates-plugin-orgs-s24…
Browse files Browse the repository at this point in the history
…-r25_D3D-6027

Updates for S24 and R25 and adds Orgs support
  • Loading branch information
cedricpinson authored Oct 28, 2021
2 parents d06ef20 + 17de642 commit 5bcc393
Show file tree
Hide file tree
Showing 91 changed files with 3,267 additions and 2,247 deletions.
52 changes: 29 additions & 23 deletions dependencies/WIN/PIL/BlpImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,33 +286,36 @@ def decode(self, buffer):
raise OSError("Truncated Blp file") from e
return 0, 0

def _safe_read(self, length):
return ImageFile._safe_read(self.fd, length)

def _read_palette(self):
ret = []
for i in range(256):
try:
b, g, r, a = struct.unpack("<4B", self.fd.read(4))
b, g, r, a = struct.unpack("<4B", self._safe_read(4))
except struct.error:
break
ret.append((b, g, r, a))
return ret

def _read_blp_header(self):
(self._blp_compression,) = struct.unpack("<i", self.fd.read(4))
(self._blp_compression,) = struct.unpack("<i", self._safe_read(4))

(self._blp_encoding,) = struct.unpack("<b", self.fd.read(1))
(self._blp_alpha_depth,) = struct.unpack("<b", self.fd.read(1))
(self._blp_alpha_encoding,) = struct.unpack("<b", self.fd.read(1))
(self._blp_mips,) = struct.unpack("<b", self.fd.read(1))
(self._blp_encoding,) = struct.unpack("<b", self._safe_read(1))
(self._blp_alpha_depth,) = struct.unpack("<b", self._safe_read(1))
(self._blp_alpha_encoding,) = struct.unpack("<b", self._safe_read(1))
(self._blp_mips,) = struct.unpack("<b", self._safe_read(1))

self.size = struct.unpack("<II", self.fd.read(8))
self.size = struct.unpack("<II", self._safe_read(8))

if self.magic == b"BLP1":
# Only present for BLP1
(self._blp_encoding,) = struct.unpack("<i", self.fd.read(4))
(self._blp_subtype,) = struct.unpack("<i", self.fd.read(4))
(self._blp_encoding,) = struct.unpack("<i", self._safe_read(4))
(self._blp_subtype,) = struct.unpack("<i", self._safe_read(4))

self._blp_offsets = struct.unpack("<16I", self.fd.read(16 * 4))
self._blp_lengths = struct.unpack("<16I", self.fd.read(16 * 4))
self._blp_offsets = struct.unpack("<16I", self._safe_read(16 * 4))
self._blp_lengths = struct.unpack("<16I", self._safe_read(16 * 4))


class BLP1Decoder(_BLPBaseDecoder):
Expand All @@ -324,7 +327,7 @@ def _load(self):
if self._blp_encoding in (4, 5):
data = bytearray()
palette = self._read_palette()
_data = BytesIO(self.fd.read(self._blp_lengths[0]))
_data = BytesIO(self._safe_read(self._blp_lengths[0]))
while True:
try:
(offset,) = struct.unpack("<B", _data.read(1))
Expand All @@ -346,13 +349,14 @@ def _load(self):
def _decode_jpeg_stream(self):
from PIL.JpegImagePlugin import JpegImageFile

(jpeg_header_size,) = struct.unpack("<I", self.fd.read(4))
jpeg_header = self.fd.read(jpeg_header_size)
self.fd.read(self._blp_offsets[0] - self.fd.tell()) # What IS this?
data = self.fd.read(self._blp_lengths[0])
(jpeg_header_size,) = struct.unpack("<I", self._safe_read(4))
jpeg_header = self._safe_read(jpeg_header_size)
self._safe_read(self._blp_offsets[0] - self.fd.tell()) # What IS this?
data = self._safe_read(self._blp_lengths[0])
data = jpeg_header + data
data = BytesIO(data)
image = JpegImageFile(data)
Image._decompression_bomb_check(image.size)
self.tile = image.tile # :/
self.fd = image.fp
self.mode = image.mode
Expand All @@ -369,7 +373,7 @@ def _load(self):
# Uncompressed or DirectX compression

if self._blp_encoding == BLP_ENCODING_UNCOMPRESSED:
_data = BytesIO(self.fd.read(self._blp_lengths[0]))
_data = BytesIO(self._safe_read(self._blp_lengths[0]))
while True:
try:
(offset,) = struct.unpack("<B", _data.read(1))
Expand All @@ -383,20 +387,20 @@ def _load(self):
linesize = (self.size[0] + 3) // 4 * 8
for yb in range((self.size[1] + 3) // 4):
for d in decode_dxt1(
self.fd.read(linesize), alpha=bool(self._blp_alpha_depth)
self._safe_read(linesize), alpha=bool(self._blp_alpha_depth)
):
data += d

elif self._blp_alpha_encoding == BLP_ALPHA_ENCODING_DXT3:
linesize = (self.size[0] + 3) // 4 * 16
for yb in range((self.size[1] + 3) // 4):
for d in decode_dxt3(self.fd.read(linesize)):
for d in decode_dxt3(self._safe_read(linesize)):
data += d

elif self._blp_alpha_encoding == BLP_ALPHA_ENCODING_DXT5:
linesize = (self.size[0] + 3) // 4 * 16
for yb in range((self.size[1] + 3) // 4):
for d in decode_dxt5(self.fd.read(linesize)):
for d in decode_dxt5(self._safe_read(linesize)):
data += d
else:
raise BLPFormatError(
Expand All @@ -413,9 +417,11 @@ def _load(self):
self.set_as_raw(bytes(data))


Image.register_open(
BlpImageFile.format, BlpImageFile, lambda p: p[:4] in (b"BLP1", b"BLP2")
)
def _accept(prefix):
return prefix[:4] in (b"BLP1", b"BLP2")


Image.register_open(BlpImageFile.format, BlpImageFile, _accept)
Image.register_extension(BlpImageFile.format, ".blp")

Image.register_decoder("BLP1", BLP1Decoder)
Expand Down
47 changes: 22 additions & 25 deletions dependencies/WIN/PIL/BmpImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@


from . import Image, ImageFile, ImagePalette
from ._binary import i8
from ._binary import i16le as i16
from ._binary import i32le as i32
from ._binary import o8
Expand All @@ -52,14 +51,14 @@ def _accept(prefix):


def _dib_accept(prefix):
return i32(prefix[:4]) in [12, 40, 64, 108, 124]
return i32(prefix) in [12, 40, 64, 108, 124]


# =============================================================================
# Image plugin for the Windows BMP format.
# =============================================================================
class BmpImageFile(ImageFile.ImageFile):
""" Image plugin for the Windows Bitmap format (BMP) """
"""Image plugin for the Windows Bitmap format (BMP)"""

# ------------------------------------------------------------- Description
format_description = "Windows Bitmap"
Expand All @@ -71,7 +70,7 @@ class BmpImageFile(ImageFile.ImageFile):
vars()[k] = v

def _bitmap(self, header=0, offset=0):
""" Read relevant info about the BMP """
"""Read relevant info about the BMP"""
read, seek = self.fp.read, self.fp.seek
if header:
seek(header)
Expand All @@ -87,44 +86,42 @@ def _bitmap(self, header=0, offset=0):
# -------------------------------------------------- IBM OS/2 Bitmap v1
# ----- This format has different offsets because of width/height types
if file_info["header_size"] == 12:
file_info["width"] = i16(header_data[0:2])
file_info["height"] = i16(header_data[2:4])
file_info["planes"] = i16(header_data[4:6])
file_info["bits"] = i16(header_data[6:8])
file_info["width"] = i16(header_data, 0)
file_info["height"] = i16(header_data, 2)
file_info["planes"] = i16(header_data, 4)
file_info["bits"] = i16(header_data, 6)
file_info["compression"] = self.RAW
file_info["palette_padding"] = 3

# --------------------------------------------- Windows Bitmap v2 to v5
# v3, OS/2 v2, v4, v5
elif file_info["header_size"] in (40, 64, 108, 124):
file_info["y_flip"] = i8(header_data[7]) == 0xFF
file_info["y_flip"] = header_data[7] == 0xFF
file_info["direction"] = 1 if file_info["y_flip"] else -1
file_info["width"] = i32(header_data[0:4])
file_info["width"] = i32(header_data, 0)
file_info["height"] = (
i32(header_data[4:8])
i32(header_data, 4)
if not file_info["y_flip"]
else 2 ** 32 - i32(header_data[4:8])
else 2 ** 32 - i32(header_data, 4)
)
file_info["planes"] = i16(header_data[8:10])
file_info["bits"] = i16(header_data[10:12])
file_info["compression"] = i32(header_data[12:16])
file_info["planes"] = i16(header_data, 8)
file_info["bits"] = i16(header_data, 10)
file_info["compression"] = i32(header_data, 12)
# byte size of pixel data
file_info["data_size"] = i32(header_data[16:20])
file_info["data_size"] = i32(header_data, 16)
file_info["pixels_per_meter"] = (
i32(header_data[20:24]),
i32(header_data[24:28]),
i32(header_data, 20),
i32(header_data, 24),
)
file_info["colors"] = i32(header_data[28:32])
file_info["colors"] = i32(header_data, 28)
file_info["palette_padding"] = 4
self.info["dpi"] = tuple(
int(x / 39.3701 + 0.5) for x in file_info["pixels_per_meter"]
)
self.info["dpi"] = tuple(x / 39.3701 for x in file_info["pixels_per_meter"])
if file_info["compression"] == self.BITFIELDS:
if len(header_data) >= 52:
for idx, mask in enumerate(
["r_mask", "g_mask", "b_mask", "a_mask"]
):
file_info[mask] = i32(header_data[36 + idx * 4 : 40 + idx * 4])
file_info[mask] = i32(header_data, 36 + idx * 4)
else:
# 40 byte headers only have the three components in the
# bitfields masks, ref:
Expand Down Expand Up @@ -260,14 +257,14 @@ def _bitmap(self, header=0, offset=0):
]

def _open(self):
""" Open file, check magic number and read header """
"""Open file, check magic number and read header"""
# read 14 bytes: magic number, filesize, reserved, header final offset
head_data = self.fp.read(14)
# choke if the file does not have the required magic bytes
if not _accept(head_data):
raise SyntaxError("Not a BMP file")
# read the start position of the BMP image data (u32)
offset = i32(head_data[10:14])
offset = i32(head_data, 10)
# load bitmap information (offset=raster info)
self._bitmap(offset=offset)

Expand Down
7 changes: 3 additions & 4 deletions dependencies/WIN/PIL/CurImagePlugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
# See the README file for information on usage and redistribution.
#
from . import BmpImagePlugin, Image
from ._binary import i8
from ._binary import i16le as i16
from ._binary import i32le as i32

Expand Down Expand Up @@ -48,17 +47,17 @@ def _open(self):

# pick the largest cursor in the file
m = b""
for i in range(i16(s[4:])):
for i in range(i16(s, 4)):
s = self.fp.read(16)
if not m:
m = s
elif i8(s[0]) > i8(m[0]) and i8(s[1]) > i8(m[1]):
elif s[0] > m[0] and s[1] > m[1]:
m = s
if not m:
raise TypeError("No cursors were found")

# load as bitmap
self._bitmap(i32(m[12:]) + offset)
self._bitmap(i32(m, 12) + offset)

# patch up the bitmap height
self._size = self.size[0], self.size[1] // 2
Expand Down
Loading

0 comments on commit 5bcc393

Please sign in to comment.