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())