88 lines
2.9 KiB
Python
88 lines
2.9 KiB
Python
"""Resize the flicker frame PNGs to embeddable JPGs and inject into the HTML report.
|
|
|
|
Reads flicker_investigation_handover.html, replaces the static "ul.tight" frame
|
|
list in Section 1 with an inline gallery of base64-embedded JPGs, and writes
|
|
back the same file.
|
|
"""
|
|
import base64
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
from PIL import Image
|
|
|
|
REPO = Path(__file__).parent
|
|
PICS = REPO / "data" / "pics"
|
|
HTML = REPO / "flicker_investigation_continued.html"
|
|
TMP = REPO / ".embed_tmp"
|
|
|
|
# (filename, caption)
|
|
FRAMES = [
|
|
("frame0362.png", "Frame 362 — baseline. Clean image."),
|
|
("frame0363.png", "Frame 363 — flicker. Vertical displacement; content recognisable but geometry wrong."),
|
|
("frame0370.png", "Frame 370 — flicker. Same vertical shift pattern."),
|
|
("frame0376.png", "Frame 376 — flicker. Lower-amplitude shift."),
|
|
("frame0381.png", "Frame 381 — flicker (most dramatic). Multi-band tearing; multiple partial frames stacked vertically."),
|
|
("frame0382.png", "Frame 382 — flicker. Frame after the dramatic shift; partial recovery still showing artifacts."),
|
|
]
|
|
|
|
|
|
def resize_to_jpg(src: Path, dst: Path, width: int = 800, quality: int = 75) -> None:
|
|
"""Resize src to width px and write as JPG at given quality, via Pillow."""
|
|
img = Image.open(src)
|
|
if img.mode != "RGB":
|
|
img = img.convert("RGB")
|
|
w, h = img.size
|
|
if w > width:
|
|
new_h = int(h * width / w)
|
|
img = img.resize((width, new_h), Image.LANCZOS)
|
|
img.save(dst, "JPEG", quality=quality, optimize=True)
|
|
|
|
|
|
def main() -> int:
|
|
if not HTML.exists():
|
|
print(f"missing {HTML}", file=sys.stderr); return 1
|
|
|
|
TMP.mkdir(exist_ok=True)
|
|
blocks = []
|
|
for fname, caption in FRAMES:
|
|
src = PICS / fname
|
|
if not src.exists():
|
|
print(f"skip (missing): {src}"); continue
|
|
dst = TMP / (src.stem + ".jpg")
|
|
resize_to_jpg(src, dst)
|
|
b64 = base64.b64encode(dst.read_bytes()).decode("ascii")
|
|
kb = len(b64) * 3 // 4 // 1024
|
|
blocks.append(
|
|
f'<figure class="frame">\n'
|
|
f' <img src="data:image/jpeg;base64,{b64}" alt="{fname}">\n'
|
|
f' <figcaption>{caption}</figcaption>\n'
|
|
f'</figure>'
|
|
)
|
|
print(f"embedded {fname} -> {kb} KB")
|
|
|
|
if not blocks:
|
|
print("no frames embedded; HTML unchanged"); return 1
|
|
|
|
gallery = (
|
|
'<div class="frame-gallery">\n'
|
|
+ "\n".join(blocks)
|
|
+ "\n</div>"
|
|
)
|
|
|
|
html = HTML.read_text(encoding="utf-8")
|
|
|
|
placeholder = "<!-- FRAME_GALLERY_PLACEHOLDER -->"
|
|
if placeholder not in html:
|
|
print(f"WARNING: placeholder {placeholder!r} not found in HTML; "
|
|
"no embedding done", file=sys.stderr)
|
|
return 1
|
|
new_html = html.replace(placeholder, gallery, 1)
|
|
|
|
HTML.write_text(new_html, encoding="utf-8")
|
|
print(f"wrote {HTML} ({len(new_html)//1024} KB)")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
sys.exit(main())
|