File size: 5,372 Bytes
f6dcb1f
3778796
f6dcb1f
 
71e45d9
 
 
 
 
 
 
 
 
 
 
 
 
 
1414db8
 
71e45d9
 
3778796
 
 
 
 
 
f6dcb1f
71e45d9
 
 
f6dcb1f
 
71e45d9
 
 
 
 
 
1414db8
 
 
71e45d9
 
 
 
 
1414db8
 
 
 
71e45d9
 
 
 
 
 
1414db8
71e45d9
 
3778796
 
 
f6dcb1f
71e45d9
 
3778796
71e45d9
 
 
 
 
 
3778796
71e45d9
3778796
f6dcb1f
71e45d9
f6dcb1f
3778796
f6dcb1f
3778796
f6dcb1f
71e45d9
 
 
 
 
3778796
71e45d9
f6dcb1f
71e45d9
 
 
 
3778796
71e45d9
 
df27c04
 
 
71e45d9
 
 
 
 
 
3778796
71e45d9
3778796
 
71e45d9
df27c04
3778796
 
71e45d9
 
 
 
 
 
 
3778796
 
 
 
 
71e45d9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3778796
71e45d9
 
 
 
 
 
3778796
f6dcb1f
 
1414db8
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
import gradio as gr
import matplotlib.pyplot as plt
from io import BytesIO
from PIL import Image, ImageDraw, ImageFont
import textwrap
import os
import matplotlib

def get_system_fonts():
    fonts = []
    for font in matplotlib.font_manager.findSystemFonts(fontpaths=None, fontext='ttf'):
        font_name = os.path.basename(font)
        fonts.append(font_name)
    return sorted(set(fonts))

def parse_color(color):
    if isinstance(color, str) and color.startswith('rgba'):
        color = color.replace('rgba', '').strip('()').split(',')
        return tuple(int(float(c.strip())) for c in color[:3])
    return color

def render_plain_text_image(text, font_size, width, height, bg_color, text_color, font_name, align):
    bg_color = parse_color(bg_color)
    text_color = parse_color(text_color)

    img = Image.new("RGB", (width, height), color=bg_color)
    draw = ImageDraw.Draw(img)

    try:
        font_path = matplotlib.font_manager.findfont(font_name)
        font = ImageFont.truetype(font_path, font_size)
    except Exception:
        font = ImageFont.load_default()

    margin = 10
    max_width = width - 2 * margin
    lines = []
    for line in text.split('\n'):
        lines.extend(textwrap.wrap(line, width=int(max_width / font_size * 1.8)))

    # Use getbbox() instead of getsize()
    bbox = font.getbbox('Ay')
    line_height = bbox[3] - bbox[1]
    total_text_height = line_height * len(lines)

    y = (height - total_text_height) // 2

    for line in lines:
        # Use getbbox() to get line width
        bbox = font.getbbox(line)
        line_width = bbox[2] - bbox[0]
        
        if align == 'Left':
            x = margin
        elif align == 'Center':
            x = (width - line_width) // 2
        else:  # Right alignment
            x = width - line_width - margin
            
        draw.text((x, y), line, fill=text_color, font=font)
        y += line_height

    return img

def render_math_image(text, font_size, width, height, bg_color, text_color):
    bg_color = parse_color(bg_color)
    text_color = parse_color(text_color)

    fig, ax = plt.subplots(figsize=(width / 100, height / 100), facecolor=bg_color)
    ax.set_facecolor(bg_color)
    ax.axis('off')

    if not (text.startswith(r"$") and text.endswith(r"$")):
        text = rf"${text}$"

    ax.text(0.5, 0.5, text, fontsize=font_size, ha='center', va='center', color=text_color)

    buf = BytesIO()
    plt.savefig(buf, format='png', bbox_inches='tight', pad_inches=0)
    plt.close(fig)

    buf.seek(0)
    return Image.open(buf)

def text_to_image(input_text, font_size, width, height, bg_color, text_color, mode, font_name, align, image_format):
    if mode == "Plain Text":
        img = render_plain_text_image(input_text, font_size, width, height, bg_color, text_color, font_name, align)
    elif mode == "LaTeX Math":
        img = render_math_image(input_text, font_size, width, height, bg_color, text_color)
    else:
        return "Invalid mode selected!"

    buf = BytesIO()
    img.save(buf, format=image_format)
    buf.seek(0)
    return buf

def handle_file_upload(file, font_size, width, height, bg_color, text_color, mode, font_name, align, image_format):
    if file is not None:
        file_path = file[0]
        with open(file_path, "r", encoding="utf-8") as f:
            text = f.read()
        return text_to_image(text, font_size, width, height, bg_color, text_color, mode, font_name, align, image_format)
    return "No file uploaded!"

font_list = get_system_fonts()
default_font = "DejaVuSans.ttf" if "DejaVuSans.ttf" in font_list else font_list[0]

with gr.Blocks() as demo:
    gr.Markdown("# 🖼️ Text to Image Converter")

    with gr.Row():
        input_text = gr.Textbox(label="Enter Text", placeholder="Type or paste text here...")
        file_input = gr.File(label="Upload a Text File", type="filepath")

    with gr.Row():
        font_size = gr.Slider(10, 100, value=30, label="Font Size")
        font_name = gr.Dropdown(choices=font_list, value=default_font, label="Font")
        align = gr.Radio(["Left", "Center", "Right"], label="Text Alignment", value="Center")

    with gr.Row():
        width = gr.Slider(200, 2000, value=800, label="Image Width")
        height = gr.Slider(200, 2000, value=600, label="Image Height")

    with gr.Row():
        bg_color = gr.ColorPicker(label="Background Color", value="#FFFFFF")
        text_color = gr.ColorPicker(label="Text Color", value="#000000")

    with gr.Row():
        mode = gr.Radio(["Plain Text", "LaTeX Math"], label="Rendering Mode", value="Plain Text")
        image_format = gr.Radio(["PNG", "JPEG"], label="Image Format", value="PNG")

    output_image = gr.Image(label="Generated Image")

    with gr.Row():
        convert_button = gr.Button("Convert Text to Image")
        file_convert_button = gr.Button("Convert File to Image")

    convert_button.click(
        text_to_image,
        inputs=[
            input_text, font_size, width, height, bg_color, text_color,
            mode, font_name, align, image_format
        ],
        outputs=output_image
    )

    file_convert_button.click(
        handle_file_upload,
        inputs=[
            file_input, font_size, width, height, bg_color, text_color,
            mode, font_name, align, image_format
        ],
        outputs=output_image
    )

demo.launch()