pi features docs
This commit is contained in:
52
image_handler.py
Normal file
52
image_handler.py
Normal file
@@ -0,0 +1,52 @@
|
||||
"""Status image functions — loading, alpha compositing, and WS transmission."""
|
||||
|
||||
import json
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
from PIL import Image
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
IMG_DIR = Path(__file__).parent / "assets" / "img"
|
||||
STATUS_IMG_SIZE = 120
|
||||
MONOCHROME_THRESHOLD = 120
|
||||
|
||||
|
||||
def load_status_image(path: Path) -> bytes:
|
||||
"""Load a PNG, convert to 1-bit 120x120 monochrome bitmap (MSB-first, black=1).
|
||||
|
||||
Transparent pixels are composited onto white so they don't render as black.
|
||||
"""
|
||||
img = Image.open(path)
|
||||
|
||||
# Composite transparent pixels onto white background
|
||||
if img.mode in ("RGBA", "LA", "PA"):
|
||||
bg = Image.new("RGBA", img.size, (255, 255, 255, 255))
|
||||
bg.paste(img, mask=img.split()[-1])
|
||||
img = bg
|
||||
|
||||
img = img.convert("L")
|
||||
|
||||
# Resize to fit within 120x120, preserving aspect ratio
|
||||
img.thumbnail((STATUS_IMG_SIZE, STATUS_IMG_SIZE), Image.LANCZOS)
|
||||
|
||||
# Paste centered onto white canvas
|
||||
canvas = Image.new("L", (STATUS_IMG_SIZE, STATUS_IMG_SIZE), 255)
|
||||
x_off = (STATUS_IMG_SIZE - img.width) // 2
|
||||
y_off = (STATUS_IMG_SIZE - img.height) // 2
|
||||
canvas.paste(img, (x_off, y_off))
|
||||
|
||||
# Threshold to 1-bit: black (< 128) -> 1, white -> 0
|
||||
bw = canvas.point(lambda p: 1 if p < MONOCHROME_THRESHOLD else 0, "1")
|
||||
raw = bw.tobytes()
|
||||
log.info("Status image loaded: %s -> %d bytes", path.name, len(raw))
|
||||
return raw
|
||||
|
||||
|
||||
async def send_status_image(ws, img_bytes: bytes):
|
||||
"""Send a status image over the WebSocket (text header + binary payload)."""
|
||||
header = json.dumps({"type": "status_image", "width": STATUS_IMG_SIZE, "height": STATUS_IMG_SIZE})
|
||||
await ws.send(header)
|
||||
await ws.send(img_bytes)
|
||||
log.info("Sent status image (%d bytes)", len(img_bytes))
|
||||
Reference in New Issue
Block a user