31 lines
1.4 KiB
Python
31 lines
1.4 KiB
Python
"""Exact whole-image comparisons and measured interior click selection.
|
|
|
|
CONTRACT: no mask or tolerance may turn a whole-output difference into PASS.
|
|
INVARIANT: coordinates of every differing pixel are retained on failure.
|
|
"""
|
|
from PIL import Image, ImageChops
|
|
import re
|
|
COLORS = {(35,68,204),(32,208,160)}
|
|
def analyze(im):
|
|
mask=Image.new('L',im.size)
|
|
values=[255 if c in COLORS else 0 for c in im.get_flattened_data()]
|
|
mask.putdata(values)
|
|
return {'count':sum(v!=0 for v in values),'bbox':mask.getbbox()}
|
|
def compare(a,b):
|
|
assert a.size==b.size
|
|
points=[{'x':i%a.width,'y':i//a.width,'before':x,'after':y}
|
|
for i,(x,y) in enumerate(zip(a.get_flattened_data(),b.get_flattened_data())) if x!=y]
|
|
return {'equal':not points,'changed':len(points),'bbox':ImageChops.difference(a,b).getbbox(),'pixels':points}
|
|
def interior(im):
|
|
box=analyze(im)['bbox'];assert box
|
|
x1,y1,x2,y2=box;assert x2-x1>40 and y2-y1>40
|
|
x,y=(x1+x2)//2,(y1+y2)//2
|
|
assert all(im.getpixel((xx,yy)) in COLORS for xx in range(x-20,x+21) for yy in range(y-20,y+21))
|
|
return x,y
|
|
|
|
def button_pair(lines):
|
|
events=[re.search(r'BUTTON ns=(\d+) serial=(\d+) button=(\d+) state=(\d+)',x) for x in lines]
|
|
events=[tuple(map(int,x.groups())) for x in events if x]
|
|
assert len(events)==2 and [x[2:] for x in events]==[(273,1),(273,0)],events
|
|
assert all(x[1]>0 for x in events)
|
|
return [{'ns':x[0],'serial':x[1],'button':x[2],'state':x[3]} for x in events]
|