advent22/api/advent22_api/routers/_image.py

84 lines
2.1 KiB
Python
Raw Normal View History

2022-10-14 22:09:23 +00:00
from dataclasses import dataclass
import numpy as np
from PIL import Image, ImageDraw, ImageFont
@dataclass
class AdventImage:
img: Image.Image
@classmethod
async def load_standard(cls, fp) -> "AdventImage":
"""
Bild laden und einen quadratischen Ausschnitt
aus der Mitte nehmen
"""
# Bild laden
img = Image.open(fp=fp)
# Größen bestimmen
width, height = img.size
square = min(width, height)
# Bild zuschneiden und skalieren
img = img.crop(box=(
int((width - square)/2),
int((height - square)/2),
int((width + square)/2),
int((height + square)/2),
))
img = img.resize(
size=(500, 500),
resample=Image.ANTIALIAS,
)
# Farbmodell festlegen
return cls(img=img.convert("RGB"))
async def get_text_box(
self,
xy: tuple[float, float],
text: str | bytes,
font: "ImageFont._Font",
anchor: str | None = "mm",
**text_kwargs,
) -> tuple[int, int, int, int] | None:
"""
Koordinaten (links, oben, rechts, unten) des betroffenen
Rechtecks bestimmen, wenn das Bild `img` mit einem Text
versehen wird
"""
# Neues 1-Bit Bild, gleiche Größe
mask = Image.new(mode="1", size=self.img.size, color=0)
# Text auf Maske auftragen
ImageDraw.Draw(mask).text(
xy=xy,
text=text,
font=font,
anchor=anchor,
fill=1,
**text_kwargs,
)
# betroffenen Pixelbereich bestimmen
return mask.getbbox()
async def get_average_color(
self,
box: tuple[int, int, int, int],
) -> tuple[int, int, int]:
"""
Durchschnittsfarbe eines rechteckigen Ausschnitts in
einem Bild `img` berechnen
"""
pixel_data = self.img.crop(box).getdata()
mean_color: np.ndarray = np.mean(pixel_data, axis=0)
return tuple(mean_color.astype(int).tolist())