import gradio as gr import base64 import requests import io import os from PIL import Image, ImageDraw, ImageFont, ImageOps # ========================================== # 1. ПОДГОТОВКА РЕСУРСОВ (Шрифт) # ========================================== FONT_URL = "https://github.com/google/fonts/raw/main/ofl/nunito/Nunito-Black.ttf" FONT_PATH = "Nunito-Black.ttf" def download_font(): if not os.path.exists(FONT_PATH): print("Скачивание шрифта Nunito...") try: r = requests.get(FONT_URL) with open(FONT_PATH, 'wb') as f: f.write(r.content) print("Шрифт скачан.") except Exception as e: print(f"Ошибка скачивания шрифта: {e}") # Скачиваем шрифт при запуске download_font() # ========================================== # 2. ЛОГИКА ГЕНЕРАЦИИ НА PYTHON (Для API) # ========================================== BG_COLOR = (225, 56, 57) # #E13839 GRADIENT_START = (255, 255, 255) # #FFFFFF GRADIENT_END = (255, 172, 199) # #FFACC7 def create_gradient_image(width, height): """Создает вертикальный градиент.""" base = Image.new('RGB', (width, height), GRADIENT_START) top = Image.new('RGB', (width, height), GRADIENT_END) mask = Image.new('L', (width, height)) mask_data = [] for y in range(height): mask_data.extend([int(255 * (y / height))] * width) mask.putdata(mask_data) base.paste(top, (0, 0), mask) return base def generate_text_icon(text): """API: Генерация иконки с адаптивным текстом.""" if not text: return None W, H = 512, 512 # 1. Фон img = Image.new('RGBA', (W, H), BG_COLOR + (255,)) # 2. Создание маски текста # Начинаем с большого шрифта и уменьшаем, пока не влезет font_size = 400 padding = 40 max_w = W - (padding * 2) max_h = H - (padding * 2) try: font = ImageFont.truetype(FONT_PATH, font_size) except: font = ImageFont.load_default() while font_size > 20: try: font = ImageFont.truetype(FONT_PATH, font_size) except: pass # fallback # Используем getbbox для точного измерения dummy_draw = ImageDraw.Draw(Image.new('L', (1, 1))) bbox = dummy_draw.textbbox((0, 0), text, font=font) text_w = bbox[2] - bbox[0] text_h = bbox[3] - bbox[1] if text_w <= max_w and text_h <= max_h: break font_size -= 10 # Рисуем текст в маску (белый текст на черном фоне) mask_img = Image.new('L', (W, H), 0) draw = ImageDraw.Draw(mask_img) # Центрирование # Пересчитываем bbox для финального шрифта bbox = draw.textbbox((0, 0), text, font=font) text_w = bbox[2] - bbox[0] text_h = bbox[3] - bbox[1] x = (W - text_w) / 2 - bbox[0] y = (H - text_h) / 2 - bbox[1] - (bbox[1]/2) # Небольшая коррекция baseline draw.text((x, y), text, font=font, fill=255) # 3. Градиент gradient = create_gradient_image(W, H) # 4. Наложение градиента по маске текста на красный фон img.paste(gradient, (0, 0), mask_img) return img def generate_image_icon(input_image, scale_percent): """API: Генерация иконки из картинки (SVG/PNG) с ресайзом.""" if input_image is None: return None W, H = 512, 512 # 1. Фон final_img = Image.new('RGBA', (W, H), BG_COLOR + (255,)) # 2. Обработка входного изображения # Если это SVG, Gradio/PIL может сконвертировать его в растр при загрузке, # но лучше подавать PNG. PIL откроет как растр. if isinstance(input_image, str): # Если путь icon = Image.open(input_image).convert("RGBA") else: # Если объект icon = input_image.convert("RGBA") # Масштабирование scale = scale_percent / 100.0 # Базовый размер - пытаемся вписать в 300px (как в JS версии) и умножаем на scale base_size = 300 * scale # Сохраняем пропорции ratio = icon.width / icon.height new_w = int(base_size) new_h = int(base_size / ratio) icon_resized = icon.resize((new_w, new_h), Image.Resampling.LANCZOS) # Центрирование offset_x = (W - new_w) // 2 offset_y = (H - new_h) // 2 # 3. Создаем маску из альфа-канала иконки # Если иконка не имеет прозрачности, считаем её сплошной if "A" in icon_resized.getbands(): mask = icon_resized.split()[-1] else: mask = Image.new('L', icon_resized.size, 255) # 4. Градиент gradient = create_gradient_image(W, H) # Вырезаем кусок градиента под размер иконки (чтобы градиент был глобальным на холсте) gradient_crop = gradient.crop((offset_x, offset_y, offset_x + new_w, offset_y + new_h)) # 5. Наложение final_img.paste(gradient_crop, (offset_x, offset_y), mask) return final_img # ========================================== # 3. HTML КОД (Frontend) # ========================================== html_content = """
Кликни на стикер для выделения.
Delete = удалить.
SVG (Градиентный фон)
Клик или Drop