Backend: receipt upload -> LLM vision extraction (OpenAI-compatible, provider-agnostic), item review/edit, per-group splitting against Cospend projects/members, highlight+upload via WebDAV, public share link, bill creation via Cospend's OCS API (verified against real source, not just doc summaries). Frontend: capture -> review -> group -> summary flow as an installable PWA. install.sh / run.sh (venv + npm, tmux session) instead of Docker, per the ~/Projects/gain pattern.
33 lines
1.1 KiB
Python
33 lines
1.1 KiB
Python
"""Draws highlight boxes over selected items on the original receipt image."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import io
|
|
|
|
from PIL import Image, ImageDraw
|
|
|
|
_BOX_COLOR = (255, 210, 0) # translucent yellow highlighter look
|
|
_BOX_WIDTH = 4
|
|
|
|
|
|
def highlight_items(image_bytes: bytes, bboxes: list[list[float]]) -> bytes:
|
|
"""`bboxes` are normalized [x, y, w, h] (0-1). Returns JPEG bytes."""
|
|
base = Image.open(io.BytesIO(image_bytes)).convert("RGBA")
|
|
overlay = Image.new("RGBA", base.size, (0, 0, 0, 0))
|
|
draw = ImageDraw.Draw(overlay)
|
|
w, h = base.size
|
|
|
|
for bbox in bboxes:
|
|
if not bbox or len(bbox) != 4:
|
|
continue
|
|
x, y, bw, bh = bbox
|
|
left, top = x * w, y * h
|
|
right, bottom = (x + bw) * w, (y + bh) * h
|
|
draw.rectangle([left, top, right, bottom], fill=(*_BOX_COLOR, 70))
|
|
draw.rectangle([left, top, right, bottom], outline=(*_BOX_COLOR, 255), width=_BOX_WIDTH)
|
|
|
|
combined = Image.alpha_composite(base, overlay).convert("RGB")
|
|
out = io.BytesIO()
|
|
combined.save(out, format="JPEG", quality=90)
|
|
return out.getvalue()
|