Files
matrix-screen-controller/核桃派软件源代码/app/display/diagnostics.py
T

134 lines
4.1 KiB
Python

from __future__ import annotations
from PIL import Image, ImageDraw
from .text_renderer import TextOptions, render_text
DIAGNOSTIC_MODES = {
"corners_lines",
"row_bands",
"address_check",
"address_bit_0",
"address_bit_1",
"address_bit_2",
"address_bit_3",
"address_bit_4",
"text_ok123",
"clear",
}
def render_diagnostic(mode: str, size: tuple[int, int] = (64, 64)) -> Image.Image:
if mode not in DIAGNOSTIC_MODES:
allowed = ", ".join(sorted(DIAGNOSTIC_MODES))
raise ValueError(f"diagnostic mode must be one of: {allowed}")
if mode == "clear":
return Image.new("RGB", size, (0, 0, 0))
if mode == "corners_lines":
return _render_corners_lines(size)
if mode == "row_bands":
return _render_row_bands(size)
if mode == "address_check":
return _render_address_check(size)
if mode.startswith("address_bit_"):
return _render_address_bit(int(mode.rsplit("_", 1)[1]), size)
return render_text(TextOptions(text="OK123", size=12, x=4, y=24), size=size)
def _render_corners_lines(size: tuple[int, int]) -> Image.Image:
width, height = size
image = Image.new("RGB", size, (0, 0, 0))
draw = ImageDraw.Draw(image)
for y, color in ((0, (80, 80, 80)), (31, (255, 180, 0)), (32, (0, 180, 255)), (63, (80, 80, 80))):
if y < height:
draw.line((0, y, width - 1, y), fill=color)
for x in (0, width - 1):
draw.line((x, 0, x, height - 1), fill=(80, 80, 80))
marker = 4
draw.rectangle((0, 0, marker, marker), fill=(255, 0, 0))
draw.rectangle((width - marker - 1, 0, width - 1, marker), fill=(0, 255, 0))
draw.rectangle((0, height - marker - 1, marker, height - 1), fill=(0, 0, 255))
draw.rectangle((width - marker - 1, height - marker - 1, width - 1, height - 1), fill=(255, 255, 255))
return image
def _render_row_bands(size: tuple[int, int]) -> Image.Image:
width, height = size
image = Image.new("RGB", size, (0, 0, 0))
draw = ImageDraw.Draw(image)
colors = (
(255, 0, 0),
(255, 120, 0),
(255, 255, 0),
(0, 255, 0),
(0, 255, 255),
(0, 0, 255),
(180, 0, 255),
(255, 255, 255),
)
band_height = max(1, height // len(colors))
for index, color in enumerate(colors):
y0 = index * band_height
y1 = height - 1 if index == len(colors) - 1 else min(height - 1, y0 + band_height - 1)
draw.rectangle((0, y0, width - 1, y1), fill=color)
draw.line((0, y0, width - 1, y0), fill=(0, 0, 0))
return image
def _render_address_check(size: tuple[int, int]) -> Image.Image:
width, height = size
image = Image.new("RGB", size, (0, 0, 0))
draw = ImageDraw.Draw(image)
bit_colors = (
(255, 0, 0),
(0, 255, 0),
(0, 0, 255),
(255, 255, 0),
(255, 0, 255),
)
segment_width = max(1, width // len(bit_colors))
for y in range(height):
for bit, color in enumerate(bit_colors):
if y & (1 << bit):
x0 = bit * segment_width
x1 = width - 1 if bit == len(bit_colors) - 1 else min(width - 1, x0 + segment_width - 2)
draw.line((x0, y, x1, y), fill=color)
diagonal_x = min(width - 1, y)
draw.point((diagonal_x, y), fill=(255, 255, 255))
draw.point((width - 1 - diagonal_x, y), fill=(80, 80, 80))
for y in (0, 31, 32, 63):
if y < height:
draw.line((0, y, width - 1, y), fill=(255, 255, 255))
return image
def _render_address_bit(bit: int, size: tuple[int, int]) -> Image.Image:
width, height = size
image = Image.new("RGB", size, (0, 0, 0))
draw = ImageDraw.Draw(image)
colors = (
(255, 0, 0),
(0, 255, 0),
(0, 0, 255),
(255, 255, 0),
(255, 0, 255),
)
color = colors[bit]
for y in range(height):
if y & (1 << bit):
draw.line((0, y, width - 1, y), fill=color)
for y in (0, 31, 32, 63):
if y < height:
draw.line((0, y, width - 1, y), fill=(255, 255, 255))
return image