from io import BytesIO from PIL import Image, ImageDraw, ImageFilter Image.MAX_IMAGE_PIXELS = 50_000_000 def insert_logo( background, logo, scale_factor=0.095, padding=8, radius=15, quality=95 ): background = background.copy().convert("RGBA") # Логотип logo = logo.copy().convert("RGBA") # Масштабирование logo_w, logo_h = logo.size back_w, back_h = background.size new_w = max(1, int(back_w * scale_factor)) ratio = logo_w / logo_h if logo_h > 0 else 1 new_h = max(1, int(new_w / ratio)) logo = logo.resize((new_w, new_h), Image.Resampling.LANCZOS) # === Создаём полностью прозрачный фон === transparent = Image.new("RGBA", (new_w, new_h), (0, 0, 0, 0)) # Компонуем логотип на полностью прозрачный фон (убирает все артефакты) logo = Image.alpha_composite(transparent, logo) # === Маска закругления === mask = Image.new("L", (new_w, new_h), 0) draw = ImageDraw.Draw(mask) draw.rounded_rectangle([(0, 0), (new_w-1, new_h-1)], radius=radius, fill=255) mask = mask.filter(ImageFilter.SMOOTH) # Применяем маску через composite (самый чистый способ) logo = Image.composite(logo, transparent, mask) # Позиция (нижний левый угол) pos_x = padding pos_y = back_h - new_h - padding if pos_y < 0: pos_y = 0 # Вставка background.paste(logo, (pos_x, pos_y), logo) # Сохранение out = BytesIO() background.convert("RGB").save(out, format="JPEG", quality=quality, optimize=True) out.seek(0) return out async def convert_bio_to_webp(bio: BytesIO, quality: int = 95) -> BytesIO: bio.seek(0) im = Image.open(bio).convert("RGB") out = BytesIO() im.save(out, format="WEBP", quality=quality, method=6) out.seek(0) return out