mirror of
https://mau.dev/maunium/synapse.git
synced 2024-11-14 05:52:37 +01:00
Handle image transparency better when thumbnailing. (#9473)
Properly uses RGBA mode for 1- and 8-bit images with transparency (instead of RBG mode).
This commit is contained in:
parent
3ce650057d
commit
075c16b410
3 changed files with 30 additions and 11 deletions
1
changelog.d/9473.bugfix
Normal file
1
changelog.d/9473.bugfix
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Fix long-standing bug when generating thumbnails for some images with transparency: `TypeError: cannot unpack non-iterable int object`.
|
|
@ -96,9 +96,14 @@ class Thumbnailer:
|
||||||
def _resize(self, width: int, height: int) -> Image:
|
def _resize(self, width: int, height: int) -> Image:
|
||||||
# 1-bit or 8-bit color palette images need converting to RGB
|
# 1-bit or 8-bit color palette images need converting to RGB
|
||||||
# otherwise they will be scaled using nearest neighbour which
|
# otherwise they will be scaled using nearest neighbour which
|
||||||
# looks awful
|
# looks awful.
|
||||||
if self.image.mode in ["1", "P"]:
|
#
|
||||||
self.image = self.image.convert("RGB")
|
# If the image has transparency, use RGBA instead.
|
||||||
|
if self.image.mode in ["1", "L", "P"]:
|
||||||
|
mode = "RGB"
|
||||||
|
if self.image.info.get("transparency", None) is not None:
|
||||||
|
mode = "RGBA"
|
||||||
|
self.image = self.image.convert(mode)
|
||||||
return self.image.resize((width, height), Image.ANTIALIAS)
|
return self.image.resize((width, height), Image.ANTIALIAS)
|
||||||
|
|
||||||
def scale(self, width: int, height: int, output_type: str) -> BytesIO:
|
def scale(self, width: int, height: int, output_type: str) -> BytesIO:
|
||||||
|
|
|
@ -105,7 +105,7 @@ class MediaStorageTests(unittest.HomeserverTestCase):
|
||||||
self.assertEqual(test_body, body)
|
self.assertEqual(test_body, body)
|
||||||
|
|
||||||
|
|
||||||
@attr.s
|
@attr.s(slots=True, frozen=True)
|
||||||
class _TestImage:
|
class _TestImage:
|
||||||
"""An image for testing thumbnailing with the expected results
|
"""An image for testing thumbnailing with the expected results
|
||||||
|
|
||||||
|
@ -117,13 +117,15 @@ class _TestImage:
|
||||||
test should just check for success.
|
test should just check for success.
|
||||||
expected_scaled: The expected bytes from scaled thumbnailing, or None if
|
expected_scaled: The expected bytes from scaled thumbnailing, or None if
|
||||||
test should just check for a valid image returned.
|
test should just check for a valid image returned.
|
||||||
|
expected_found: True if the file should exist on the server, or False if
|
||||||
|
a 404 is expected.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
data = attr.ib(type=bytes)
|
data = attr.ib(type=bytes)
|
||||||
content_type = attr.ib(type=bytes)
|
content_type = attr.ib(type=bytes)
|
||||||
extension = attr.ib(type=bytes)
|
extension = attr.ib(type=bytes)
|
||||||
expected_cropped = attr.ib(type=Optional[bytes])
|
expected_cropped = attr.ib(type=Optional[bytes], default=None)
|
||||||
expected_scaled = attr.ib(type=Optional[bytes])
|
expected_scaled = attr.ib(type=Optional[bytes], default=None)
|
||||||
expected_found = attr.ib(default=True, type=bool)
|
expected_found = attr.ib(default=True, type=bool)
|
||||||
|
|
||||||
|
|
||||||
|
@ -153,6 +155,21 @@ class _TestImage:
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
# small png with transparency.
|
||||||
|
(
|
||||||
|
_TestImage(
|
||||||
|
unhexlify(
|
||||||
|
b"89504e470d0a1a0a0000000d49484452000000010000000101000"
|
||||||
|
b"00000376ef9240000000274524e5300010194fdae0000000a4944"
|
||||||
|
b"4154789c636800000082008177cd72b60000000049454e44ae426"
|
||||||
|
b"082"
|
||||||
|
),
|
||||||
|
b"image/png",
|
||||||
|
b".png",
|
||||||
|
# Note that we don't check the output since it varies across
|
||||||
|
# different versions of Pillow.
|
||||||
|
),
|
||||||
|
),
|
||||||
# small lossless webp
|
# small lossless webp
|
||||||
(
|
(
|
||||||
_TestImage(
|
_TestImage(
|
||||||
|
@ -162,8 +179,6 @@ class _TestImage:
|
||||||
),
|
),
|
||||||
b"image/webp",
|
b"image/webp",
|
||||||
b".webp",
|
b".webp",
|
||||||
None,
|
|
||||||
None,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
# an empty file
|
# an empty file
|
||||||
|
@ -172,9 +187,7 @@ class _TestImage:
|
||||||
b"",
|
b"",
|
||||||
b"image/gif",
|
b"image/gif",
|
||||||
b".gif",
|
b".gif",
|
||||||
None,
|
expected_found=False,
|
||||||
None,
|
|
||||||
False,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
Loading…
Reference in a new issue