File size: 4,547 Bytes
dc2831e
 
269525c
 
0483ea7
7690d86
dc2831e
 
7690d86
 
 
 
 
 
 
 
 
 
 
dc2831e
269525c
7690d86
 
 
7d205dd
 
0063f85
7d205dd
0063f85
7d205dd
 
 
 
 
 
412ae09
 
 
7d205dd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
412ae09
 
 
7d205dd
 
 
 
7690d86
7d205dd
7690d86
 
 
 
 
269525c
7690d86
 
 
 
 
 
 
dc2831e
7690d86
dc2831e
b70654b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7690d86
 
 
b70654b
0483ea7
7690d86
 
 
 
 
 
 
0063f85
7690d86
 
 
 
 
 
dc2831e
a6146e8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import gradio as gr
import requests
from PIL import Image, ImageDraw, ImageFont
import textwrap
import os
from concurrent.futures import ThreadPoolExecutor, as_completed

def download_image(prompt, index):
    try:
        url = f"https://pollinations.ai/p/{prompt}"
        response = requests.get(url, timeout=10)
        response.raise_for_status()
        image_filename = f'generated_image_{index}.jpg'
        with open(image_filename, 'wb') as file:
            file.write(response.content)
        return image_filename
    except requests.RequestException as e:
        print(f"Error downloading image {index}: {e}")
        return None

def add_text_to_image(image_path, text):
    try:
        img = Image.open(image_path)
        draw = ImageDraw.Draw(img)
        
        # Use a default font if custom font is not available
        try:
            font = ImageFont.truetype("arial.ttf", 30)
        except IOError:
            font = ImageFont.load_default().font_variant(size=30)
        
        # Calculate text size and position
        img_width, img_height = img.size
        max_text_width = int(img_width * 0.9)  # 90% of image width
        lines = textwrap.wrap(text, width=40)
        
        # Use getbbox instead of getsize
        line_height = font.getbbox("hg")[3] + 5  # Add some padding
        text_height = line_height * len(lines)
        
        # Create semi-transparent background
        overlay = Image.new('RGBA', img.size, (0, 0, 0, 0))
        overlay_draw = ImageDraw.Draw(overlay)
        overlay_draw.rectangle([(0, img_height - text_height - 20), (img_width, img_height)], 
                               fill=(0, 0, 0, 180))
        
        # Paste the overlay onto the original image
        img = img.convert('RGBA')
        img = Image.alpha_composite(img, overlay)
        draw = ImageDraw.Draw(img)
        
        # Add text
        y_text = img_height - text_height - 10
        for line in lines:
            # Use getbbox for line width calculation
            bbox = font.getbbox(line)
            line_width = bbox[2] - bbox[0]
            x_text = (img_width - line_width) / 2
            draw.text((x_text, y_text), line, font=font, fill=(255, 255, 255, 255))
            y_text += line_height
        
        img_with_text = f'text_added_{os.path.basename(image_path)}'
        img = img.convert('RGB')
        img.save(img_with_text)
        return img_with_text
    except Exception as e:
        print(f"Error adding text to image: {e}")
        return None

    with ThreadPoolExecutor(max_workers=5) as executor:
        future_to_idx = {executor.submit(process_line, idx, line): idx for idx, line in enumerate(lines)}
        for future in progress.tqdm(as_completed(future_to_idx), total=len(lines), desc="Processing images"):
            idx = future_to_idx[future]
            result = future.result()
            if result:
                images_with_text.append((idx, result))
    
    return [img for _, img in sorted(images_with_text)]

def process_story_lines(story, progress=gr.Progress()):
    lines = [line.strip() for line in story.split('\n') if line.strip()]
    images_with_text = []
    
    def process_line(idx, line):
        prompt = line.replace(" ", "_")
        img_file = download_image(prompt, idx)
        if img_file:
            return add_text_to_image(img_file, line)
        return None

    with ThreadPoolExecutor(max_workers=5) as executor:
        future_to_idx = {executor.submit(process_line, idx, line): idx for idx, line in enumerate(lines)}
        for future in progress.tqdm(as_completed(future_to_idx), total=len(lines), desc="Processing images"):
            idx = future_to_idx[future]
            result = future.result()
            if result:
                images_with_text.append((idx, result))
    
    return [img for _, img in sorted(images_with_text)]

def visualize_story_images(story):
    if not story.strip():
        return []
    return process_story_lines(story)

with gr.Blocks() as iface:
    gr.Markdown("# Story Visualizer")
    
    with gr.Row():
        story_input = gr.Textbox(lines=10, placeholder="Enter your story here...", label="Story Input")
        visualize_button = gr.Button("Visualize Story")
    
    gallery_output = gr.Gallery(label="Visualized Story", show_label=False, elem_id="gallery", columns=2, rows=2, height="auto")
    
    visualize_button.click(
        fn=visualize_story_images,
        inputs=[story_input],
        outputs=[gallery_output]
    )

iface.launch(share=True)