mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-28 23:00:21 -04:00
113 lines
4.3 KiB
Python
113 lines
4.3 KiB
Python
#!/usr/bin/env python3
|
|
import argparse
|
|
import json
|
|
from pathlib import Path
|
|
|
|
from PIL import Image, ImageChops
|
|
|
|
GBA_FPS = 262144 / 4389
|
|
|
|
LANDMARKS = [
|
|
("copyright_white", 14), ("copyright_fade_in", 20), ("copyright_hold_end", 155),
|
|
("copyright_fade_out", 162), ("scene1_fade_in", 212), ("gf_logo_blend_in", 345),
|
|
("gf_letters", 420), ("gf_logo_blend_out", 480), ("drop_ripple", 500), ("sparkles_pan", 800),
|
|
("flygon_silhouette", 1060), ("scene1_white", 1225), ("scene2_fade_in", 1250), ("scene2_mid", 1700),
|
|
("scene2_torchic_trip", 2000), ("scene2_white", 2200), ("scene3_pokeball", 2300),
|
|
("scene3_groudon_narrow", 2345), ("scene3_groudon", 2440), ("scene3_kyogre", 2560),
|
|
("scene3_kyogre_zoom", 2690), ("scene3_clouds", 2800), ("scene3_rayquaza", 3000),
|
|
("scene3_orb", 3140), ("title_logo", 3270), ("title_shine", 3300), ("title_banner", 3560),
|
|
("title_settle", 3700),
|
|
]
|
|
|
|
|
|
def load(path):
|
|
return Image.open(path).convert("RGB")
|
|
|
|
|
|
def diff(a, b, bits5, tolerance=0):
|
|
if bits5:
|
|
a = a.point(lambda v: v >> 3)
|
|
b = b.point(lambda v: v >> 3)
|
|
d = ImageChops.difference(a, b)
|
|
r, g, bl = d.split()
|
|
m = ImageChops.lighter(ImageChops.lighter(r, g), bl).point(lambda v: 255 if v > tolerance else 0)
|
|
return 100.0 * m.histogram()[255] / (a.width * a.height)
|
|
|
|
|
|
def big(a, b):
|
|
return diff(a, b, False, 8)
|
|
|
|
|
|
def main():
|
|
ap = argparse.ArgumentParser()
|
|
ap.add_argument("--ours", required=True)
|
|
ap.add_argument("--ref", required=True)
|
|
ap.add_argument("--offset", type=int, default=12)
|
|
ap.add_argument("--window", type=int, default=3)
|
|
ap.add_argument("--sweep", action="store_true")
|
|
ap.add_argument("--json")
|
|
a = ap.parse_args()
|
|
ours, ref = Path(a.ours), Path(a.ref)
|
|
cache = {}
|
|
|
|
def our(n):
|
|
if n not in cache:
|
|
p = ours / ("f%05d.png" % n)
|
|
cache[n] = load(p) if p.exists() else None
|
|
return cache[n]
|
|
|
|
rows = []
|
|
for name, r in LANDMARKS:
|
|
rp = ref / ("frame-%06d.png" % r)
|
|
if not rp.exists():
|
|
continue
|
|
rimg = load(rp)
|
|
base = r - a.offset
|
|
best = None
|
|
for d in range(-a.window, a.window + 1):
|
|
o = our(base + d)
|
|
if o is None:
|
|
continue
|
|
pct = diff(rimg, o, True)
|
|
if best is None or pct < best[1] or (pct == best[1] and abs(d) < abs(best[0])):
|
|
best = (d, pct)
|
|
at = our(base)
|
|
exact = diff(rimg, at, True) if at is not None else None
|
|
coarse = big(rimg, at) if at is not None else None
|
|
rows.append({
|
|
"landmark": name, "ref_frame": r, "ref_s": round(r / GBA_FPS, 4),
|
|
"engine_tick": base, "engine_s": round(base / 60, 4),
|
|
"diff_at_offset_pct": None if exact is None else round(exact, 3),
|
|
"diff_over_one_step_pct": None if coarse is None else round(coarse, 3),
|
|
"best_shift": None if best is None else best[0],
|
|
"best_diff_pct": None if best is None else round(best[1], 3),
|
|
})
|
|
print("%-24s ref=%5d engine=%5d diff@0=%7s >1step=%7s best shift=%+d diff=%7s" % (
|
|
name, r, base, "-" if exact is None else "%.3f%%" % exact,
|
|
"-" if coarse is None else "%.3f%%" % coarse,
|
|
0 if best is None else best[0], "-" if best is None else "%.3f%%" % best[1]))
|
|
if a.sweep:
|
|
worst = []
|
|
for p in sorted(ours.glob("f?????.png")):
|
|
n = int(p.stem[1:])
|
|
rp = ref / ("frame-%06d.png" % (n + a.offset))
|
|
if not rp.exists():
|
|
continue
|
|
ri, oi = load(rp), load(p)
|
|
pct = diff(ri, oi, True)
|
|
worst.append((big(ri, oi), pct, n))
|
|
worst.sort(reverse=True)
|
|
exact = sum(1 for w in worst if w[1] == 0)
|
|
near = sum(1 for w in worst if w[0] == 0)
|
|
print("sweep: %d frames, %d pixel-exact (5-bit), %d within one colour step, mean diff %.3f%%, mean >1step %.3f%%" % (
|
|
len(worst), exact, near, sum(w[1] for w in worst) / max(1, len(worst)),
|
|
sum(w[0] for w in worst) / max(1, len(worst))))
|
|
for coarse, pct, n in worst[:25]:
|
|
print(" worst engine=%5d ref=%5d >1step=%.3f%% diff=%.3f%%" % (n, n + a.offset, coarse, pct))
|
|
if a.json:
|
|
Path(a.json).write_text(json.dumps(rows, indent=1))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|