"""Erzeugt Testfotos: mehrere Visitenkarten auf einem dunklen Untergrund.""" import io import random import numpy as np from PIL import Image, ImageDraw CARD_RATIO = 85.6 / 54.0 def _card(width: int = 420, seed: int = 0) -> Image.Image: """Eine weisse Karte mit ein paar dunklen Textzeilen.""" height = round(width / CARD_RATIO) card = Image.new("RGB", (width, height), "white") draw = ImageDraw.Draw(card) rng = random.Random(seed) draw.line([(0.08 * width, 0.30 * height), (0.62 * width, 0.30 * height)], fill="black", width=6) draw.line([(0.08 * width, 0.44 * height), (0.48 * width, 0.44 * height)], fill=(70, 70, 70), width=3) for index in range(3): y = (0.62 + index * 0.10) * height draw.line( [(0.08 * width, y), ((0.30 + rng.random() * 0.35) * width, y)], fill=(90, 90, 90), width=2, ) return card def photo_with_cards(count: int = 6, size=(2400, 1800), angle_range: int = 8) -> np.ndarray: """Foto im BGR-Format mit `count` Karten in einem Raster.""" background = Image.new("RGB", size, (38, 40, 44)) rng = random.Random(count) columns = 2 if count <= 6 else 3 rows = (count + columns - 1) // columns cell_width = size[0] // columns cell_height = size[1] // rows card_width = int(min(cell_width * 0.72, cell_height * 0.72 * CARD_RATIO)) for index in range(count): column, row = index % columns, index // columns card = _card(card_width, seed=index) angle = rng.uniform(-angle_range, angle_range) rotated = card.rotate(angle, expand=True, resample=Image.BICUBIC) mask = Image.new("L", card.size, 255).rotate( angle, expand=True, resample=Image.BICUBIC ) x = column * cell_width + (cell_width - rotated.width) // 2 y = row * cell_height + (cell_height - rotated.height) // 2 background.paste(rotated, (x, y), mask) return np.asarray(background)[:, :, ::-1].copy() def photo_bytes(count: int = 6) -> bytes: array = photo_with_cards(count) buffer = io.BytesIO() Image.fromarray(array[:, :, ::-1]).save(buffer, format="JPEG", quality=92) return buffer.getvalue()