#!/usr/bin/env python3 # Part of JoeyLib, Copyright (c) 2026 Scott Duensing, under the MIT License. # See LICENSE.md for license information. # SPDX-License-Identifier: MIT """keysCells.py - read which of KEYS's named-key cells are lit off a screenshot. KEYS (examples/keys) draws a cell for each named key, lit (colour 2, green) while jlKeyDown says it is down and dark grey (colour 1) otherwise. This reads the cells of its fourth row that a port gives a second physical key for -- Return, Ctrl, Alt, Up, Down, Left, and Right -- at the middle of each, and prints one digit a cell, in that order: 1 lit, 0 not, ? neither colour. keysCells.py PNG [--at X,Y] [--scale S] --at: where the stage's top left is in the screenshot (default 0,0). --scale: screen pixels a stage pixel (default 1). """ import sys from PIL import Image # examples/keys: CELL_W x CELL_H cells GAP apart from (MARGIN_X, MARGIN_Y), # the named keys in row 4 at these columns. CELL_W = 28 CELL_H = 26 GAP = 4 MARGIN_X = 2 MARGIN_Y = 2 ROW = 4 COLUMNS = (2, 3, 4, 5, 6, 7, 8) # Return, Ctrl, Alt, Up, Down, Left, Right # KEYS's colours 1 and 2 (12-bit $333 and $0F0, each channel widened x17). UNLIT = (0x33, 0x33, 0x33) LIT = (0x00, 0xFF, 0x00) # A 15- or 16-bit screen is off by at most 8 a channel. MAX_DIST = 3 * 9 ** 2 def near(got, want): return sum((g - w) ** 2 for g, w in zip(got, want)) <= MAX_DIST def main(argv): args = argv[1:] at = (0, 0) scale = 1 png = None while args: arg = args.pop(0) if arg == "--at": at = tuple(int(v) for v in args.pop(0).split(",")) elif arg == "--scale": scale = int(args.pop(0)) else: png = arg if png is None: print(__doc__.strip(), file=sys.stderr) return 2 image = Image.open(png).convert("RGB") y = MARGIN_Y + ROW * (CELL_H + GAP) + CELL_H // 2 digits = [] for column in COLUMNS: x = MARGIN_X + column * (CELL_W + GAP) + CELL_W // 2 pixel = image.getpixel((at[0] + x * scale, at[1] + y * scale)) digits.append("1" if near(pixel, LIT) else ("0" if near(pixel, UNLIT) else "?")) print("".join(digits)) return 0 if __name__ == "__main__": sys.exit(main(sys.argv))