Linux native client
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

68 lines
2.2 KiB

"""Media compression before storage / upload (Pillow images; ffmpeg optional for A/V)."""
from __future__ import annotations
import io
import tempfile
from pathlib import Path
from PIL import Image
from imwald.core.database import Database
from imwald.core.media_compress import (
SETTING_MEDIA_COMPRESS_STRENGTH,
SETTING_MEDIA_MAX_IMAGE_WIDTH,
compress_image_bytes,
prepare_bytes_for_storage,
read_compression_strength,
read_max_image_width,
)
def _rgb_wide_png() -> bytes:
im = Image.new("RGB", (1600, 400), color=(200, 30, 30))
buf = io.BytesIO()
im.save(buf, format="PNG", compress_level=3)
return buf.getvalue()
def test_compress_image_scales_to_max_width() -> None:
raw = _rgb_wide_png()
out, mime, name = compress_image_bytes(raw, max_width=1000, strength=1, original_name="x.png")
assert mime == "image/jpeg"
assert name.endswith(".jpg")
im = Image.open(io.BytesIO(out))
assert im.size[0] <= 1000
def test_strength_stronger_yields_smaller_or_equal_jpeg() -> None:
raw = _rgb_wide_png()
light, _, _ = compress_image_bytes(raw, max_width=1000, strength=0, original_name="w.png")
strong, _, _ = compress_image_bytes(raw, max_width=1000, strength=2, original_name="w.png")
assert len(strong) <= len(light)
def test_read_settings_from_db() -> None:
with tempfile.TemporaryDirectory() as td:
db = Database(Path(td) / "m.sqlite")
db.connect()
assert read_compression_strength(db) == 1
assert read_max_image_width(db) == 1000
db.set_setting(SETTING_MEDIA_COMPRESS_STRENGTH, "2")
db.set_setting(SETTING_MEDIA_MAX_IMAGE_WIDTH, "1200")
assert read_compression_strength(db) == 2
assert read_max_image_width(db) == 1200
def test_prepare_bytes_image_round_trip() -> None:
raw = _rgb_wide_png()
with tempfile.TemporaryDirectory() as td:
db = Database(Path(td) / "m2.sqlite")
db.connect()
db.set_setting(SETTING_MEDIA_MAX_IMAGE_WIDTH, "800")
out, mime, _name = prepare_bytes_for_storage(
raw, "wide.png", mime_hint="image/png", db=db, strength=1
)
assert mime == "image/jpeg"
im = Image.open(io.BytesIO(out))
assert im.size[0] <= 800