Files
watchy/watchy-image-editor/image.py
T
2021-08-27 10:56:36 +02:00

89 lines
3.1 KiB
Python

from typing import List
from math import sqrt
from bitmap import Bitmap
class Image:
def __init__(self, name: str, width: int, height: int, empty: bool = False) -> None:
self.name = name
self.width = width
self.height = height
self.modified = False
if empty:
self.data = [0] * ((width * height) // 8)
self.modified = True
else:
self.data = []
def finalize(self) -> None:
if self.width == 0:
pixels = len(self.data) * 8
width = int(sqrt(pixels))
while width > 1 and pixels % width != 0:
width -= 1
self.width = width
self.height = pixels // width
def add_data(self, raw_data: List[str]) -> None:
for v in raw_data:
self.data += [int(v, 16)]
def __get_position(self, x: int, y: int) -> int:
real_width = (len(self.data) * 8) // self.height
return y * real_width + x
def get_pixel(self, x: int, y: int) -> bool:
position = self.__get_position(x, y)
chunk_id = position // 8
return self.data[chunk_id] & (1 << (7 - position % 8)) > 0
def set_pixel(self, x: int, y: int, v: bool) -> None:
position = self.__get_position(x, y)
chunk_id = position // 8
if v != self.get_pixel(x, y):
if v:
self.data[chunk_id] |= 1 << (7 - position % 8)
else:
self.data[chunk_id] &= ~(1 << (7 - position % 8))
self.modified = True
def __get_color_bytes(self) -> bytes:
output = bytes()
for y in range(self.height):
for x in range(self.width):
if self.get_pixel(x, y):
output += bytes([0, 0, 0])
else:
output += bytes([255, 255, 255])
return output
def export_bmp(self, path: str) -> None:
Bitmap.write_bmp(path, self.width, 3, self.__get_color_bytes())
def __set_color_bytes(self, color_depth: int, data: bytes) -> None:
for y in range(self.height):
for x in range(self.width):
position = (y * self.width + x) * color_depth
colors = data[position : position + color_depth]
mean_color = sum(c for c in colors) / color_depth
if mean_color < 128:
self.set_pixel(x, y, True)
def import_bmp(self, path: str) -> None:
self.width, self.height, color_depth, bmp_data = Bitmap.read_bmp(path)
self.data = [0] * ((self.width * self.height) // 8)
self.__set_color_bytes(color_depth, bmp_data)
def export_cpp(self) -> str:
# 16 per line
output = [
f"// '{self.name}', {self.width}x{self.height}px",
f"const unsigned char {self.name} [] PROGMEM = {{",
]
while len(self.data) > 16:
output += ["\t" + ", ".join(f"0x{v:02x}" for v in self.data[0:16]) + ","]
self.data = self.data[16:]
output += ["\t" + ", ".join(f"0x{v:02x}" for v in self.data), "};", ""]
return "\n".join(output)