import numpy as np, glob from PIL import Image files = sorted(glob.glob("an2/f*.png")) imgs = [Image.open(f) for f in files] print("PIL mode:", imgs[0].mode) idx = [np.asarray(im.convert("P") if im.mode!="P" else im, dtype=np.uint8) for im in imgs] N = len(idx); H,W = idx[0].shape; raw = H*W print(f"frames={N} size={H}x{W} raw={raw} B/frame") # --- per-pair change stats on the QUANTIZED stream --- pct = np.array([100.0*np.count_nonzero(idx[i]!=idx[i-1])/raw for i in range(1,N)]) print(f"\n--- consecutive change % (24fps, quantized) ---") print(f"mean {pct.mean():.1f} median {np.median(pct):.1f} p10 {np.percentile(pct,10):.1f} p90 {np.percentile(pct,90):.1f} max {pct.max():.1f}") print(f"pairs under 2% changed: {np.count_nonzero(pct<2.0)}/{len(pct)} ({100*np.count_nonzero(pct<2.0)/len(pct):.0f}%)") # --- threshold dedupe (twos detection) --- THRESH = 2.0 keep=[0] for i in range(1,N): if 100.0*np.count_nonzero(idx[i]!=idx[keep[-1]])/raw >= THRESH: keep.append(i) print(f"\n--- dedupe @ {THRESH}% ---") print(f"unique frames: {len(keep)}/{N} -> effective {len(keep)/12.0:.1f} fps") cp = np.array([100.0*np.count_nonzero(idx[keep[j]]!=idx[keep[j-1]])/raw for j in range(1,len(keep))]) print(f"unique-pair change %: mean {cp.mean():.1f} median {np.median(cp):.1f} p90 {np.percentile(cp,90):.1f} max {cp.max():.1f}") def encode_size(a,b,gap=4): total=0 for y in range(a.shape[0]): ra,rb=a[y],b[y] d=np.nonzero(ra!=rb)[0] if len(d)==0: continue spans=[]; s=d[0]; p=d[0] for x in d[1:]: if x-p>gap: spans.append((s,p)); s=x p=x spans.append((s,p)) total+=2 for s0,e0 in spans: seg=rb[s0:e0+1]; total+=2 i2=0 while i2=3 else r i2+=r return total sz=np.array([encode_size(idx[keep[j-1]],idx[keep[j]]) for j in range(1,len(keep))]) fps_eff=len(keep)/12.0 rate=sz.mean()*fps_eff print(f"\n--- codec estimate ---") print(f"delta bytes: mean {sz.mean():.0f} median {np.median(sz):.0f} p90 {np.percentile(sz,90):.0f} max {sz.max():.0f}") print(f"ratio vs raw: {raw/sz.mean():.1f}:1") print(f"stream rate : {rate/1024:.1f} KB/s") print(f"22min video : {rate*22*60/1048576:.0f} MB") px=cp.mean()/100*raw print(f"blit cost : ~{px*6.5/1000:.0f}k cycles/frame (budget 833k)") print(f"p90 blit : ~{np.percentile(cp,90)/100*raw*6.5/1000:.0f}k cycles")