#!/usr/bin/env python3 """Создание серии карточек для Светланы — фото БЕЗ текста из оригинала.""" import os from PIL import Image, ImageDraw, ImageFont, ImageFilter, ImageEnhance PHOTO_PATH = "/var/lib/lifeos/hermes/.hermes/cache/images/img_f654f52cfc02.jpg" OUT_DIR = "/var/lib/lifeos/hermes/previews/svetlana-cards" os.makedirs(OUT_DIR, exist_ok=True) W, H = 1080, 1920 BG_COLOR = (245, 240, 232) TEXT_COLOR = (80, 50, 35) ACCENT_COLOR = (140, 110, 80) LIGHT_COLOR = (160, 140, 120) font_title = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSerif-Bold.ttf", 52) font_body = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSerif.ttf", 40) font_small = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSerif.ttf", 32) font_tiny = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSerif.ttf", 26) def load_clean_photo(crop_bottom_ratio=0.58): """ Загрузить фото и обрезать нижнюю часть, где оригинальный текст. crop_bottom_ratio — какую долю высоты ОСТАВИТЬ (0.58 = верхние 58%). """ img = Image.open(PHOTO_PATH).convert("RGB") w, h = img.size # Обрезаем: оставляем только верхнюю часть без текста new_h = int(h * crop_bottom_ratio) img = img.crop((0, 0, w, new_h)) return img def add_soft_vignette(img): """Добавить мягкое затемнение к нижней части фото для плавного перехода.""" w, h = img.size overlay = Image.new("RGBA", (w, h), (0, 0, 0, 0)) for y in range(int(h * 0.5), h): alpha = int((y - h * 0.5) / (h * 0.5) * 120) for x in range(w): overlay.putpixel((x, y), (0, 0, 0, min(alpha, 100))) img = img.convert("RGBA") img = Image.alpha_composite(img, overlay) return img.convert("RGB") def draw_centered(draw, text, font, color, cx, y): bbox = draw.textbbox((0, 0), text, font=font) tw = bbox[2] - bbox[0] x = cx - tw // 2 draw.text((x, y), text, font=font, fill=color) def make_card(filename, top_lines, photo_ratio=0.52, bottom_lines=None): """ Создать карточку. top_lines — текст поверх фото (в светлом цвете) photo_ratio — доля высоты под фото bottom_lines — текст под фото на бежевом фоне """ card = Image.new("RGB", (W, H), BG_COLOR) draw = ImageDraw.Draw(card) # Фото photo = load_clean_photo(crop_bottom_ratio=0.56) photo_h = int(H * photo_ratio) photo_w = int(photo_h * photo.width / photo.height) if photo_w > W: photo_w = W photo_h = int(photo_w * photo.height / photo.width) photo = photo.resize((photo_w, photo_h), Image.LANCZOS) # Виньетка photo = add_soft_vignette(photo) # Размещаем фото сверху x_off = (W - photo_w) // 2 card.paste(photo, (x_off, 0)) # Полупрозрачная подложка для текста на фото if top_lines: text_y_start = 30 # Подложка overlay_h = len(top_lines) * 52 + 60 overlay_y = text_y_start - 15 overlay = Image.new("RGBA", (W, overlay_h), (0, 0, 0, 80)) card.paste(overlay, (0, overlay_y), overlay) y = text_y_start for line in top_lines: draw_centered(draw, line, font_body, (255, 245, 235), W // 2, y) y += 52 # Текст под фото if bottom_lines: y = photo_h + 40 for line in bottom_lines: if line.startswith("# "): draw_centered(draw, line[2:], font_title, TEXT_COLOR, W // 2, y) y += 70 elif line.startswith("## "): draw_centered(draw, line[3:], font_body, ACCENT_COLOR, W // 2, y) y += 55 elif line == "": y += 20 elif line.startswith("— "): draw_centered(draw, line, font_small, ACCENT_COLOR, W // 2, y) y += 40 elif line.startswith("~~"): draw_centered(draw, line[2:], font_tiny, LIGHT_COLOR, W // 2, y) y += 35 else: draw_centered(draw, line, font_body, TEXT_COLOR, W // 2, y) y += 50 path = os.path.join(OUT_DIR, filename) card.save(path, "PNG", quality=95) return path # ===== КАРТОЧКА 1: «Я всё успеваю» ===== make_card( "01_vse_uspevayu.png", top_lines=["Знакомо?"], photo_ratio=0.56, bottom_lines=[ "", "Я всё успеваю.", "А внутри — пустота.", ] ) # ===== КАРТОЧКА 2: «Усталость» ===== make_card( "02_ustalost.png", top_lines=["О чём молчат успешные..."], photo_ratio=0.50, bottom_lines=[ "", "Я долго думала,", "что усталость —", "это когда НЕ успел.", "", "А оказалось —", "когда всё успел,", "но тебя в этом списке", "не было.", ] ) # ===== КАРТОЧКА 3: «Где я беру энергию (прод.)» ===== make_card( "03_energiya_prod.png", top_lines=["Где я беру энергию"], photo_ratio=0.42, bottom_lines=[ "## (продолжение)", "", "4. Перестать быть удобной.", "Половина дел — чужие ожидания.", "", "5. Вкус еды. Не на бегу.", "Почувствовать каждый кусочек.", "", "6. Разрешить себе НЕ быть", "продуктивной. Хотя бы час.", ] ) # ===== КАРТОЧКА 4: «Знакомо?» ===== make_card( "04_znakomo.png", top_lines=["Знакомо?"], photo_ratio=0.52, bottom_lines=[ "", "Когда дел — вагон,", "всё горишь, справляешься,", "а вечером смотришь", "в потолок и...", "ничего не чувствуешь.", "", "~~Было такое? ❤️ Да 💬 Нет", ] ) # ===== КАРТОЧКА 5: «Телефон» ===== make_card( "05_telefon.png", top_lines=["Представьте телефон:"], photo_ratio=0.42, bottom_lines=[ "зарядка — 100%.", "", "Но 40 приложений в фоне.", "Экран горит — всё ок.", "А батарея тает.", "", "— Так и мы. Снаружи порядок,", "внутри — ноль.", ] ) # ===== КАРТОЧКА 6: «Где я беру энергию» ===== make_card( "06_energiya.png", top_lines=["Где я беру энергию"], photo_ratio=0.40, bottom_lines=[ "", "1. 10 минут утром —", "просто быть.", "Не планировать, не скроллить.", "", "2. Спрашивать себя:", "хочу или должна?", "", "3. Тело. Босиком по траве.", "Потянуться. Подышать.", ] ) print("✅ Готово! Все 6 карточек:") for f in sorted(os.listdir(OUT_DIR)): if f.endswith('.png') and f != 'create_cards.py': sz = os.path.getsize(os.path.join(OUT_DIR, f)) // 1024 print(f" {f} — {sz} KB")