All checks were successful
Java Maven 3.9.9 & JDK 26 CI/CD Pipeline / build-and-deploy (push) Successful in 3m22s
53 lines
1.8 KiB
Python
53 lines
1.8 KiB
Python
import io
|
|
from pathlib import Path
|
|
|
|
from PIL import Image, ImageOps
|
|
|
|
from .base import ImageAttachment
|
|
|
|
|
|
INLINE_IMAGE_MAX_BYTES = 2_000_000
|
|
PREVIEW_TARGET_BYTES = 1_900_000
|
|
WECOM_FILE_MAX_BYTES = 20_000_000
|
|
TELEGRAM_PHOTO_MAX_BYTES = 10_000_000
|
|
TELEGRAM_FILE_MAX_BYTES = 50_000_000
|
|
|
|
|
|
def compressed_preview(image: ImageAttachment) -> ImageAttachment:
|
|
if len(image.data) <= INLINE_IMAGE_MAX_BYTES:
|
|
return image
|
|
|
|
with Image.open(io.BytesIO(image.data)) as source:
|
|
source.load()
|
|
working = ImageOps.exif_transpose(source)
|
|
if working.mode in {"RGBA", "LA"}:
|
|
background = Image.new("RGB", working.size, "white")
|
|
alpha = working.getchannel("A")
|
|
background.paste(working.convert("RGB"), mask=alpha)
|
|
working = background
|
|
elif working.mode != "RGB":
|
|
working = working.convert("RGB")
|
|
|
|
current = working
|
|
while True:
|
|
for quality in (90, 82, 74, 66, 58, 50, 42, 34):
|
|
output = io.BytesIO()
|
|
current.save(
|
|
output,
|
|
format="JPEG",
|
|
quality=quality,
|
|
optimize=True,
|
|
progressive=True,
|
|
)
|
|
data = output.getvalue()
|
|
if len(data) <= PREVIEW_TARGET_BYTES:
|
|
name = f"{Path(image.filename).stem}-preview.jpg"
|
|
return ImageAttachment(name, "image/jpeg", data)
|
|
width, height = current.size
|
|
if min(width, height) <= 128:
|
|
raise RuntimeError("image cannot be compressed below preview limit")
|
|
current = current.resize(
|
|
(max(1, int(width * 0.8)), max(1, int(height * 0.8))),
|
|
Image.Resampling.LANCZOS,
|
|
)
|