TextToImage / app.py
ArrcttacsrjksX's picture
Update app.py
71e45d9 verified
raw
history blame
5.98 kB
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
# Function to get available system fonts
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))
# Function to parse color
def parse_color(color):
"""Convert RGBA string to RGB tuple if necessary."""
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]) # Convert to (R, G, B)
return color # If already valid, return as is
# Function to render plain text as an image
def render_plain_text_image(text, font_size, width, height, bg_color, text_color, font_name, align):
"""Convert plain text to an image with the given parameters."""
bg_color = parse_color(bg_color)
text_color = parse_color(text_color)
# Create blank image
img = Image.new("RGB", (width, height), color=bg_color)
draw = ImageDraw.Draw(img)
# Load font
try:
font_path = matplotlib.font_manager.findfont(font_name)
font = ImageFont.truetype(font_path, font_size)
except Exception:
font = ImageFont.load_default()
# Text wrapping
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)))
# Calculate total text height
line_height = font.getsize('Ay')[1]
total_text_height = line_height * len(lines)
# Starting position
y = (height - total_text_height) // 2
for line in lines:
line_width = font.getsize(line)[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
# Function to render math (LaTeX) as an image
def render_math_image(text, font_size, width, height, bg_color, text_color):
"""Convert LaTeX-formatted text to an image."""
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')
# Ensure LaTeX formatting is correct
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)
# Main function to handle input
def text_to_image(input_text, font_size, width, height, bg_color, text_color, mode, font_name, align, image_format):
"""Determine whether to use plain text or LaTeX rendering."""
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!"
# Save image to buffer
buf = BytesIO()
img.save(buf, format=image_format)
buf.seek(0)
return buf
# Function to handle file upload
def handle_file_upload(file, font_size, width, height, bg_color, text_color, mode, font_name, align, image_format):
"""Extract text from file and convert to an image."""
if file is not None:
text = file.read().decode("utf-8") # Read and decode text file
return text_to_image(text, font_size, width, height, bg_color, text_color, mode, font_name, align, image_format)
return "No file uploaded!"
# Get list of system fonts
font_list = get_system_fonts()
default_font = "DejaVuSans.ttf" if "DejaVuSans.ttf" in font_list else font_list[0]
# Gradio Interface
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="file")
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()