fix(artwork): letterbox images and back alpha art with black
This commit is contained in:
1 parent
50a9a735f7
commit
e14a349c2d
2 files changed
+85
-12
No files matched your search
+22
-6
@@ -230,22 +230,38 @@ async def fetch(client: httpx.AsyncClient, url: str) -> bytes | None:
|
||||
|
||||
|
||||
def fit_image(data: bytes, width: int, height: int):
|
||||
"""Decode and center-crop an image to exactly ``width`` x ``height`` cells."""
|
||||
"""Decode and letterbox an image into exactly ``width`` x ``height`` cells.
|
||||
|
||||
Scale to fit, never crop. Square album art fills the box either way, but a
|
||||
wide station wordmark (Bassdrive's logo is 3:1) used to be centre-cropped
|
||||
down to a zoomed slice of its middle. The padding stays transparent, so
|
||||
the mosaic behind the artwork shows through instead of a black bar.
|
||||
"""
|
||||
try:
|
||||
from PIL import Image, ImageOps
|
||||
|
||||
with Image.open(BytesIO(data)) as source:
|
||||
# A PNG with transparency is drawn *over* the mosaic, which reads
|
||||
# as noise behind a logo; composite those onto black instead.
|
||||
has_alpha = source.mode in ("RGBA", "LA", "PA", "RGBa", "La") or (
|
||||
"transparency" in source.info
|
||||
)
|
||||
image = source.convert("RGBA")
|
||||
cell_width, cell_height = cell_size()
|
||||
target = (
|
||||
max(1, width * cell_width),
|
||||
max(1, height * cell_height),
|
||||
)
|
||||
return ImageOps.fit(
|
||||
image,
|
||||
target,
|
||||
method=Image.Resampling.LANCZOS,
|
||||
centering=(0.5, 0.5),
|
||||
fitted = ImageOps.contain(image, target, method=Image.Resampling.LANCZOS)
|
||||
background = (0, 0, 0, 255) if has_alpha else (0, 0, 0, 0)
|
||||
canvas = Image.new("RGBA", target, background)
|
||||
canvas.alpha_composite(
|
||||
fitted,
|
||||
(
|
||||
(target[0] - fitted.width) // 2,
|
||||
(target[1] - fitted.height) // 2,
|
||||
),
|
||||
)
|
||||
return canvas
|
||||
except Exception:
|
||||
return None
|
||||
Reference in new issue
Block a user