Files
ElyOffice/tests/scripts/ink.py
T
ZacharyZhang-NY b7fca0146d Ely Office: six offline-first desktop apps in Rust and GPUI
ElyDoc, ElyTable, ElyShow (LibreOfficeKit), ElyPDF (MuPDF), ElyTree (Git),
ElyMark (Milkdown and CodeMirror in CEF). ElyMail and ElyAgent follow.
2026-10-08 21:20:08 -04:00

139 lines
5.4 KiB
Python

#!/usr/bin/env python3
"""Counts bright pixels in a PNG region."""
import struct
import sys
import zlib
def read_png(path):
with open(path, "rb") as png:
data = png.read()
if data[:8] != b"\x89PNG\r\n\x1a\n":
sys.exit(f"FAIL: {path} is not a PNG")
pos, width, height, color, interlace, idat = 8, 0, 0, 0, 0, b""
while pos < len(data):
length, kind = struct.unpack(">I4s", data[pos : pos + 8])
body = data[pos + 8 : pos + 8 + length]
if kind == b"IHDR":
width, height, depth, color, _, _, interlace = struct.unpack(">IIBBBBB", body)
if depth != 8 or color not in (2, 6) or interlace != 0:
sys.exit(f"FAIL: {path} needs 8-bit RGB/RGBA, not depth {depth} color {color} interlace {interlace}")
elif kind == b"IDAT":
idat += body
elif kind == b"IEND":
break
pos += 12 + length
return width, height, 4 if color == 6 else 3, zlib.decompress(idat)
def unfilter(width, height, channels, raw):
stride = width * channels
out, previous = bytearray(), bytearray(stride)
pos = 0
for _ in range(height):
kind = raw[pos]
pos += 1
line = bytearray(raw[pos : pos + stride])
pos += stride
for i in range(stride):
left = line[i - channels] if i >= channels else 0
up = previous[i]
up_left = previous[i - channels] if i >= channels else 0
if kind == 1:
line[i] = (line[i] + left) & 0xFF
elif kind == 2:
line[i] = (line[i] + up) & 0xFF
elif kind == 3:
line[i] = (line[i] + (left + up) // 2) & 0xFF
elif kind == 4:
p = left + up - up_left
pa, pb, pc = abs(p - left), abs(p - up), abs(p - up_left)
line[i] = (line[i] + (left if pa <= pb and pa <= pc else up if pb <= pc else up_left)) & 0xFF
out += line
previous = line
return out
def region_pixels(path, x0, y0, x1, y1):
width, height, channels, raw = read_png(path)
pixels = unfilter(width, height, channels, raw)
xs, xe = int(width * x0), int(width * x1)
ys, ye = int(height * y0), int(height * y1)
out = bytearray()
for y in range(ys, ye):
for x in range(xs, xe):
at = (y * width + x) * channels
out += pixels[at : at + 3]
return xe - xs, ye - ys, bytes(out)
def region_at(path, xs, ys, width, height):
shot_w, shot_h, channels, raw = read_png(path)
pixels = unfilter(shot_w, shot_h, channels, raw)
out = bytearray()
for y in range(ys, ys + height):
for x in range(xs, xs + width):
at = (y * shot_w + x) * channels
out += pixels[at : at + 3]
return bytes(out)
def main():
if sys.argv[1] == "dist":
print(bin(int(sys.argv[2], 16) ^ int(sys.argv[3], 16)).count("1"))
return
if sys.argv[1] == "dump":
shot, out, x0, y0, x1, y1 = sys.argv[2], sys.argv[3], *map(float, sys.argv[4:8])
width, height, rgb = region_pixels(shot, x0, y0, x1, y1)
head = struct.pack("<4sII4f", b"RGBZ", width, height, x0, y0, x1, y1)
with open(out, "wb") as fixture:
fixture.write(head + zlib.compress(rgb, 9))
return
if sys.argv[1] == "cmp":
shot, fixture_path = sys.argv[2], sys.argv[3]
with open(fixture_path, "rb") as fixture:
blob = fixture.read()
magic, width, height, x0, y0, x1, y1 = struct.unpack("<4sII4f", blob[:28])
if magic != b"RGBZ":
sys.exit(f"FAIL: {fixture_path} is not an RGBZ fixture")
shot_w, shot_h, _, _ = read_png(shot)
mine = region_at(shot, int(shot_w * x0), int(shot_h * y0), width, height)
theirs = zlib.decompress(blob[28:])
if len(mine) != len(theirs):
sys.exit(f"FAIL: {fixture_path} region is {len(theirs)} bytes, the shot's is {len(mine)}")
print(sum(a != b for a, b in zip(mine, theirs, strict=True)))
return
if sys.argv[1] == "hash":
path, x0, y0, x1, y1 = sys.argv[2], *map(float, sys.argv[3:7])
width, height, channels, raw = read_png(path)
pixels = unfilter(width, height, channels, raw)
cells = []
for gy in range(16):
for gx in range(16):
total = count = 0
for y in range(int(height * (y0 + (y1 - y0) * gy / 16)), int(height * (y0 + (y1 - y0) * (gy + 1) / 16))):
for x in range(int(width * (x0 + (x1 - x0) * gx / 16)), int(width * (x0 + (x1 - x0) * (gx + 1) / 16))):
at = (y * width + x) * channels
total += (pixels[at] + pixels[at + 1] + pixels[at + 2]) / 3
count += 1
cells.append(total / max(count, 1))
mean = sum(cells) / 256
bits = 0
for cell in cells:
bits = (bits << 1) | (cell >= mean)
print(f"{bits:064x}")
return
path, x0, y0, x1, y1 = sys.argv[1], *map(float, sys.argv[2:6])
width, height, channels, raw = read_png(path)
pixels = unfilter(width, height, channels, raw)
ink = 0
for y in range(int(height * y0), int(height * y1)):
for x in range(int(width * x0), int(width * x1)):
at = (y * width + x) * channels
if pixels[at] + pixels[at + 1] + pixels[at + 2] > 380:
ink += 1
print(ink)
main()