""" preview_sample.py — zobrazí náhled fotek podle ID z databáze. Použití: python preview_sample.py 101 202 303 ... python preview_sample.py --file ids.txt # jedno ID na řádek python preview_sample.py --file ids.txt --thumb 400 """ import argparse import base64 import io import sys import tempfile import webbrowser from pathlib import Path import psycopg2 from PIL import Image # ── DB ──────────────────────────────────────────────────────────────────────── DB = dict(host="192.168.1.76", port=5432, user="vladimir.buzalka", password="Vlado7309208104++", database="fotky_buzalkovi") # ── Cesty ───────────────────────────────────────────────────────────────────── NAS_LINUX_PREFIX = "/mnt/user/ZalohaVsechObrazku/" NAS_WIN_UNC = r"\\Tower1\ZalohaVsechObrazku\\" def linux_to_win(p: str) -> Path: rel = p.removeprefix(NAS_LINUX_PREFIX).replace("/", "\\") return Path(NAS_WIN_UNC + rel) # ── Načtení dat z DB ────────────────────────────────────────────────────────── QUERY = """ SELECT z.id, z.cesta_zalohy, z.velikost, p.taken_at, p.taken_at_source, p.camera_make, p.camera_model, p.width, p.height, p.megapixels, p.gps_lat, p.gps_lon, COALESCE( (SELECT string_agg(e.error_code, ', ') FROM photo_errors e WHERE e.photo_id = p.id), '' ) AS chyby FROM zaloha_obrazku z JOIN photos p ON p.zaloha_id = z.id WHERE z.id = ANY(%s) """ def fetch_rows(ids: list[int]) -> list: conn = psycopg2.connect(**DB) cur = conn.cursor() cur.execute(QUERY, (ids,)) rows = cur.fetchall() conn.close() # zachovej původní pořadí ID order = {rid: i for i, rid in enumerate(ids)} return sorted(rows, key=lambda r: order.get(r[0], 9999)) # ── Thumbnail ───────────────────────────────────────────────────────────────── def make_thumb_b64(win_path: Path, size: int) -> str | None: try: img = Image.open(win_path) img.thumbnail((size, size), Image.LANCZOS) if img.mode not in ("RGB", "L"): img = img.convert("RGB") buf = io.BytesIO() img.save(buf, format="JPEG", quality=82) return base64.b64encode(buf.getvalue()).decode() except Exception: return None # ── HTML ────────────────────────────────────────────────────────────────────── def format_size(n) -> str: if n is None: return "?" for unit in ("B", "kB", "MB", "GB"): if n < 1024: return f"{n:.0f} {unit}" n /= 1024 return f"{n:.1f} GB" def render_html(rows: list, ids: list[int], thumb_size: int) -> str: cards = [] ok = 0 for i, row in enumerate(rows, 1): (rid, cesta, velikost, taken_at, taken_src, make_, model, width, height, mp, lat, lon, chyby) = row win_path = linux_to_win(cesta) b64 = make_thumb_b64(win_path, thumb_size) if b64: ok += 1 img_tag = f'foto' card_cls = "card" else: img_tag = '
⚠ soubor nedostupný
zkontroluj přístup na Tower1
' card_cls = "card broken" camera = " ".join(filter(None, [make_, model])) or "neznámá" date_str = taken_at.strftime("%Y-%m-%d %H:%M") if taken_at else "?" res = f"{width}×{height}" if width and height else "?" mp_str = f"{mp:.1f} Mpx" if mp else "" gps_link = ( f'📍 {lat:.4f}, {lon:.4f}' if lat and lon else "" ) chyby_html = f'
{chyby}
' if chyby else "" path_short = str(win_path).replace(NAS_WIN_UNC, "…\\") cards.append(f"""
{img_tag}
id={rid}  #{i}
{date_str} ({taken_src})
📷 {camera}
{res} {mp_str}   {format_size(velikost)}
{"
" + gps_link + "
" if gps_link else ""} {chyby_html}
{path_short}
""") missing_ids = set(ids) - {r[0] for r in rows} missing_note = "" if missing_ids: missing_note = f'
ID nenalezena v DB: {sorted(missing_ids)}
' return f""" Preview fotek ({len(rows)})

Preview fotek

Celkem ID: {len(ids)}  ·  Načteno z DB: {len(rows)}  ·  Obrázky dostupné: {ok}/{len(rows)}
{missing_note}
{"".join(cards)}
""" # ── Main ────────────────────────────────────────────────────────────────────── def main(): parser = argparse.ArgumentParser(description="Preview fotek podle ID z DB") parser.add_argument("ids", nargs="*", type=int, help="ID fotek (zaloha_obrazku.id)") parser.add_argument("--file", "-f", help="Soubor s ID (jedno na řádek)") parser.add_argument("--thumb", "-t", type=int, default=320, help="Velikost thumbnailů v px (default 320)") args = parser.parse_args() ids = list(args.ids) if args.file: with open(args.file) as fh: for line in fh: line = line.strip() if line and line.isdigit(): ids.append(int(line)) if not ids: print("Žádná ID. Zadej je jako argumenty nebo přes --file.", file=sys.stderr) sys.exit(1) print(f"Načítám {len(ids)} fotek z DB…") rows = fetch_rows(ids) print(f"Generuji thumbnaily (--thumb {args.thumb}px)…") html = render_html(rows, ids, args.thumb) tmp = tempfile.NamedTemporaryFile( suffix=".html", delete=False, mode="w", encoding="utf-8" ) tmp.write(html) tmp.close() print(f"Otevírám: {tmp.name}") webbrowser.open(f"file:///{tmp.name}") if __name__ == "__main__": main()