"""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