"""Measure the map's PAINTED legend grid, and compare the lamp bars against it. The side button columns should line up with the legend cells the map imagery paints beside them. RP412 measured ITS map at 13 + 6x102 on a 105 pitch of 640 -- a different game's art, so those numbers do not transfer. This finds ours. Two scans over a native Secondary/Radar capture: * the LEGEND: horizontal rules of the six bordered cells in the map imagery * the LAMPS: the runs of the yellow button strip at the window's left edge and reports the offset between them, which is what a misalignment looks like. py measurelegend.py """ import sys from PIL import Image def main(): path = sys.argv[1] caption = int(sys.argv[2]) if len(sys.argv) > 2 else 30 lamp_x = int(sys.argv[3]) if len(sys.argv) > 3 else 12 lx0 = int(sys.argv[4]) if len(sys.argv) > 4 else 22 lx1 = int(sys.argv[5]) if len(sys.argv) > 5 else 118 image = Image.open(path).convert("RGB") w, h = image.size px = image.load() print("capture %dx%d (client starts at y=%d)" % (w, h, caption)) # --- the legend: rows carrying a long horizontal ORANGE rule ------------- def orange(p): return p[0] > 110 and p[1] > 45 and p[2] < 90 and p[0] > p[2] + 60 rules = [] for y in range(caption, h): run = 0 best = 0 for x in range(lx0, min(lx1, w)): if orange(px[x, y]): run += 1 best = max(best, run) else: run = 0 if best >= (lx1 - lx0) * 0.55: rules.append(y - caption) # collapse adjacent rows into single rules grouped = [] for y in rules: if grouped and y - grouped[-1][-1] <= 2: grouped[-1].append(y) else: grouped.append([y]) rule_tops = [g[0] for g in grouped] print("\nlegend rules (client y): %s" % rule_tops) if len(rule_tops) >= 2: print("gaps: %s" % [rule_tops[i+1] - rule_tops[i] for i in range(len(rule_tops) - 1)]) # --- the lamps: runs of lit pixels in the button strip ------------------- lit = [] for y in range(caption, h): p = px[lamp_x, y] lit.append(p[0] > 55 and p[1] > 40 and p[2] < 90) runs = [] start = None for i, on in enumerate(lit): if on and start is None: start = i elif not on and start is not None: if i - start >= 4: runs.append((start, i - start)) start = None if start is not None and len(lit) - start >= 4: runs.append((start, len(lit) - start)) print("\nlamp bars (client y, height): %s" % runs) if len(runs) >= 2: print("lamp pitch: %s" % [runs[i+1][0] - runs[i][0] for i in range(len(runs) - 1)]) # --- compare ------------------------------------------------------------ if rule_tops and runs: print("\ncell top vs lamp top:") for i, (top, height) in enumerate(runs[:len(rule_tops)]): print(" lamp %d top=%4d nearest rule=%4d offset=%+d" % (i, top, rule_tops[i], top - rule_tops[i])) if __name__ == "__main__": main()