added demotivator

This commit is contained in:
WhatDidYouExpect 2025-07-05 20:15:55 +02:00
parent 22d454dd42
commit cd6ce96b36

View file

@ -1,28 +1,32 @@
import os import os
import re import re
from PIL import Image, ImageDraw, ImageFont import random
import shutil
import tempfile
from typing import Optional, List
from PIL import Image, ImageDraw, ImageFont, ImageOps
from modules.markovmemory import load_markov_model from modules.markovmemory import load_markov_model
from modules.sentenceprocessing import improve_sentence_coherence, rephrase_for_coherence from modules.sentenceprocessing import improve_sentence_coherence, rephrase_for_coherence
# add comments l8r
generated_sentences = set() generated_sentences = set()
async def gen_image(input_image_path, sentence_size=5, max_attempts=10):
markov_model = load_markov_model()
if not markov_model:
return None
if not os.path.isfile(input_image_path):
return None
def load_font(size): def load_font(size):
return ImageFont.truetype("assets/fonts/Impact.ttf", size=size) return ImageFont.truetype("assets/fonts/Impact.ttf", size=size)
def load_tnr(size):
return ImageFont.truetype("assets/fonts/TNR.ttf", size=size)
def draw_text_with_outline(draw, text, x, y, font): def draw_text_with_outline(draw, text, x, y, font):
outline_offsets = [(-2, -2), (-2, 2), (2, -2), (2, 2), (0, -2), (0, 2), (-2, 0), (2, 0)] outline_offsets = [(-2, -2), (-2, 2), (2, -2), (2, 2), (0, -2), (0, 2), (-2, 0), (2, 0)]
for ox, oy in outline_offsets: for ox, oy in outline_offsets:
draw.text((x + ox, y + oy), text, font=font, fill="black") draw.text((x + ox, y + oy), text, font=font, fill="black")
draw.text((x, y), text, font=font, fill="white") draw.text((x, y), text, font=font, fill="white")
def fits_in_width(text, font, max_width, draw): def fits_in_width(text, font, max_width, draw):
bbox = draw.textbbox((0, 0), text, font=font) bbox = draw.textbbox((0, 0), text, font=font)
text_width = bbox[2] - bbox[0] text_width = bbox[2] - bbox[0]
return text_width <= max_width return text_width <= max_width
def split_text_to_fit(text, font, max_width, draw): def split_text_to_fit(text, font, max_width, draw):
words = text.split() words = text.split()
for i in range(len(words), 0, -1): for i in range(len(words), 0, -1):
@ -33,6 +37,11 @@ async def gen_image(input_image_path, sentence_size=5, max_attempts=10):
midpoint = len(words) // 2 midpoint = len(words) // 2
return " ".join(words[:midpoint]), " ".join(words[midpoint:]) return " ".join(words[:midpoint]), " ".join(words[midpoint:])
async def gen_meme(input_image_path, sentence_size=5, max_attempts=10):
markov_model = load_markov_model()
if not markov_model or not os.path.isfile(input_image_path):
return None
attempt = 0 attempt = 0
while attempt < max_attempts: while attempt < max_attempts:
with Image.open(input_image_path).convert("RGBA") as img: with Image.open(input_image_path).convert("RGBA") as img:
@ -59,7 +68,7 @@ async def gen_image(input_image_path, sentence_size=5, max_attempts=10):
break break
if not response: if not response:
response = "no text generated" response = "NO TEXT GENERATED"
cleaned_response = re.sub(r'[^\w\s]', '', response).lower() cleaned_response = re.sub(r'[^\w\s]', '', response).lower()
coherent_response = rephrase_for_coherence(cleaned_response).upper() coherent_response = rephrase_for_coherence(cleaned_response).upper()
@ -91,7 +100,6 @@ async def gen_image(input_image_path, sentence_size=5, max_attempts=10):
attempt += 1 attempt += 1
with Image.open(input_image_path).convert("RGBA") as img: with Image.open(input_image_path).convert("RGBA") as img:
draw = ImageDraw.Draw(img) draw = ImageDraw.Draw(img)
width, height = img.size width, height = img.size
@ -104,3 +112,65 @@ async def gen_image(input_image_path, sentence_size=5, max_attempts=10):
draw_text_with_outline(draw, truncated, (width - text_width) / 2, 0, font) draw_text_with_outline(draw, truncated, (width - text_width) / 2, 0, font)
img.save(input_image_path) img.save(input_image_path)
return input_image_path return input_image_path
async def gen_demotivator(input_image_path, max_attempts=5):
markov_model = load_markov_model()
if not markov_model or not os.path.isfile(input_image_path):
return None
attempt = 0
while attempt < max_attempts:
with Image.open(input_image_path).convert("RGB") as img:
size = max(img.width, img.height)
square = Image.new("RGB", (size, size), "black")
x = (size - img.width) // 2
y = (size - img.height) // 2
square.paste(img, (x, y))
frame_thick = int(size * 0.0054)
framed = ImageOps.expand(square, border=frame_thick, fill="white")
landscape_w = int(size * 1.5)
caption_h = int(size * 0.3)
canvas_h = framed.height + caption_h
canvas = Image.new("RGB", (landscape_w, canvas_h), "black")
fx = (landscape_w - framed.width) // 2
canvas.paste(framed, (fx, 0))
draw = ImageDraw.Draw(canvas)
title = subtitle = None
for _ in range(20):
t = markov_model.make_sentence(tries=100, max_words=4)
s = markov_model.make_sentence(tries=100, max_words=5)
if t and s and t != s:
title = t.upper()
subtitle = s.capitalize()
break
if not title: title = "DEMOTIVATOR"
if not subtitle: subtitle = "no text generated"
title_sz = int(caption_h * 0.4)
sub_sz = int(caption_h * 0.25)
title_font = load_tnr(title_sz)
sub_font = load_tnr(sub_sz)
bbox = draw.textbbox((0, 0), title, font=title_font)
txw, txh = bbox[2] - bbox[0], bbox[3] - bbox[1]
tx = (landscape_w - txw) // 2
ty = framed.height + int(caption_h * 0.1)
draw_text_with_outline(draw, title, tx, ty, title_font)
bbox = draw.textbbox((0, 0), subtitle, font=sub_font)
sxw, sxh = bbox[2] - bbox[0], bbox[3] - bbox[1]
sx = (landscape_w - sxw) // 2
sy = ty + txh + int(caption_h * 0.05)
for ox, oy in [(-1, -1), (1, -1), (-1, 1), (1, 1)]:
draw.text((sx + ox, sy + oy), subtitle, font=sub_font, fill="black")
draw.text((sx, sy), subtitle, font=sub_font, fill="#AAAAAA")
canvas.save(input_image_path)
return input_image_path
attempt += 1
return None