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

63 lines
2.1 KiB
Python

from __future__ import annotations
import os
from PIL import Image
VALID_ORIENTATIONS = {0, 90, 180, 270}
DEFAULT_ROW_BIT_ORDER = (0, 1, 2, 3, 4)
def apply_orientation(image: Image.Image, orientation: int) -> Image.Image:
if orientation not in VALID_ORIENTATIONS:
raise ValueError("orientation must be one of 0, 90, 180, 270")
if orientation == 0:
return image.copy()
if orientation == 90:
return image.transpose(Image.Transpose.ROTATE_270)
if orientation == 180:
return image.transpose(Image.Transpose.ROTATE_180)
return image.transpose(Image.Transpose.ROTATE_90)
def get_row_bit_order() -> tuple[int, int, int, int, int]:
raw = os.environ.get("MATRIX_ROW_BIT_ORDER", "").strip()
if not raw:
return DEFAULT_ROW_BIT_ORDER
try:
values = tuple(int(part.strip()) for part in raw.split(","))
except ValueError as exc:
raise ValueError("MATRIX_ROW_BIT_ORDER must be five comma-separated integers") from exc
if len(values) != 5 or sorted(values) != [0, 1, 2, 3, 4]:
raise ValueError("MATRIX_ROW_BIT_ORDER must be a permutation of 0,1,2,3,4")
return values
def apply_row_bit_order(image: Image.Image, bit_order: tuple[int, int, int, int, int]) -> Image.Image:
if bit_order == DEFAULT_ROW_BIT_ORDER:
return image.copy()
width, height = image.size
if height % 32 != 0:
raise ValueError("row bit remap requires a display height divisible by 32")
remapped = Image.new("RGB", image.size)
for y in range(height):
scan_row = y & 31
half_offset = y - scan_row
physical_scan_row = _permute_low_five_bits(scan_row, bit_order)
source_y = half_offset + physical_scan_row
remapped.paste(image.crop((0, source_y, width, source_y + 1)), (0, y))
return remapped
def _permute_low_five_bits(value: int, bit_order: tuple[int, int, int, int, int]) -> int:
result = 0
for driver_bit, physical_bit in enumerate(bit_order):
if value & (1 << driver_bit):
result |= 1 << physical_bit
return result