ArrcttacsrjksX commited on
Commit
30fb75c
·
verified ·
1 Parent(s): 88cbee2

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +182 -72
app.py CHANGED
@@ -1,82 +1,192 @@
1
  import gradio as gr
2
- import subprocess
 
 
 
3
  import os
4
- import logging
 
5
 
6
- def setup_cli_tool():
7
- """Download and set up the CLI tool with proper error handling."""
8
- CLI_FILENAME = "Texttoimage"
9
- REPO_ID = "ArrcttacsrjksX/Texttoimage"
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
- if os.path.exists(CLI_FILENAME):
12
- logging.info(f"CLI tool already exists: {CLI_FILENAME}")
13
- os.chmod(CLI_FILENAME, 0o755) # Cấp quyền thực thi
14
- return True
15
 
16
- hf_token = os.environ.get("HF_TOKEN")
17
- if not hf_token:
18
- logging.error("HF_TOKEN environment variable not set!")
19
- return False
20
 
21
- def run_texttoimage(text, file, font_size, width, height, bg_color, text_color, mode, font, align):
22
- command = ["./Texttoimage"]
 
 
 
 
23
 
24
- if text:
25
- command += ["-t", text]
26
- elif file:
27
- command += ["-f", file.name]
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
29
- command += [
30
- "--font-size", str(font_size),
31
- "--width", str(width),
32
- "--height", str(height),
33
- "--bg-color", bg_color,
34
- "--text-color", text_color,
35
- "--mode", mode,
36
- "--font", font,
37
- "--align", align,
38
- "--output", "output.png"
39
- ]
40
-
41
- print("Running command:", " ".join(command)) # In lệnh chạy để debug
42
 
43
  try:
44
- result = subprocess.run(command, capture_output=True, text=True)
45
- print("STDOUT:", result.stdout) # In output stdout
46
- print("STDERR:", result.stderr) # In output stderr
47
-
48
- if result.returncode == 0 and os.path.exists("output.png"):
49
- return "output.png"
50
- else:
51
- return f"Error: {result.stderr or 'Output file not created!'}"
52
- except Exception as e:
53
- return f"Execution failed: {e}"
54
-
55
- # Danh sách font mẫu
56
- AVAILABLE_FONTS = [
57
- "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
58
- "/usr/share/fonts/truetype/liberation/LiberationSerif-Regular.ttf",
59
- "/usr/share/fonts/truetype/msttcorefonts/Arial.ttf"
60
- ]
61
-
62
- # Tạo giao diện Gradio
63
- demo = gr.Interface(
64
- fn=run_texttoimage,
65
- inputs=[
66
- gr.Textbox(label="Input Text", lines=3, placeholder="Nhập văn bản..."),
67
- gr.File(label="Upload File"),
68
- gr.Slider(10, 100, value=30, label="Font Size"),
69
- gr.Number(value=800, label="Image Width"),
70
- gr.Number(value=600, label="Image Height"),
71
- gr.ColorPicker(value="#FFFFFF", label="Background Color", interactive=True),
72
- gr.ColorPicker(value="#000000", label="Text Color", interactive=True),
73
- gr.Radio(["plain", "math"], value="plain", label="Rendering Mode"),
74
- gr.Dropdown(AVAILABLE_FONTS, value=AVAILABLE_FONTS[0], label="Font Selection"),
75
- gr.Radio(["left", "center", "right"], value="center", label="Text Alignment")
76
- ],
77
- outputs=gr.Image(label="Generated Image"),
78
- title="Text to Image Converter",
79
- description="Ứng dụng chuyển văn bản thành ảnh sử dụng Texttoimage."
80
- )
81
-
82
- demo.launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
+ import matplotlib.pyplot as plt
3
+ from io import BytesIO
4
+ from PIL import Image, ImageDraw, ImageFont
5
+ import textwrap
6
  import os
7
+ import matplotlib
8
+ import math
9
 
10
+ def get_system_fonts():
11
+ fonts = []
12
+ for font in matplotlib.font_manager.findSystemFonts(fontpaths=None, fontext='ttf'):
13
+ font_name = os.path.basename(font)
14
+ fonts.append(font_name)
15
+ return sorted(set(fonts))
16
+
17
+ def parse_color(color):
18
+ if isinstance(color, str) and color.startswith('rgba'):
19
+ color = color.replace('rgba', '').strip('()').split(',')
20
+ return tuple(int(float(c.strip())) for c in color[:3])
21
+ return color
22
+
23
+ def calculate_text_dimensions(text, font, max_width, margin):
24
+ lines = []
25
+ for line in text.split('\n'):
26
+ lines.extend(textwrap.wrap(line, width=int(max_width / font.size * 1.8)))
27
 
28
+ bbox = font.getbbox('Ay')
29
+ line_height = bbox[3] - bbox[1]
30
+ total_height = line_height * len(lines)
 
31
 
32
+ return lines, line_height, total_height
 
 
 
33
 
34
+ def create_text_segment(lines, start_idx, max_lines, width, height, bg_color, text_color, font, align, margin):
35
+ img = Image.new("RGB", (width, height), color=bg_color)
36
+ draw = ImageDraw.Draw(img)
37
+
38
+ bbox = font.getbbox('Ay')
39
+ line_height = bbox[3] - bbox[1]
40
 
41
+ y = margin
42
+ end_idx = min(start_idx + max_lines, len(lines))
43
+ segment_lines = lines[start_idx:end_idx]
44
+
45
+ for line in segment_lines:
46
+ bbox = font.getbbox(line)
47
+ line_width = bbox[2] - bbox[0]
48
+
49
+ if align == 'Left':
50
+ x = margin
51
+ elif align == 'Center':
52
+ x = (width - line_width) // 2
53
+ else: # Right alignment
54
+ x = width - line_width - margin
55
+
56
+ draw.text((x, y), line, fill=text_color, font=font)
57
+ y += line_height
58
 
59
+ return img, end_idx
60
+
61
+ def render_plain_text_image(text, font_size, width, height, bg_color, text_color, font_name, align):
62
+ bg_color = parse_color(bg_color)
63
+ text_color = parse_color(text_color)
64
+ margin = 10
 
 
 
 
 
 
 
65
 
66
  try:
67
+ font_path = matplotlib.font_manager.findfont(font_name)
68
+ font = ImageFont.truetype(font_path, font_size)
69
+ except Exception:
70
+ font = ImageFont.load_default()
71
+
72
+ # Calculate dimensions
73
+ max_width = width - 2 * margin
74
+ lines, line_height, total_text_height = calculate_text_dimensions(text, font, max_width, margin)
75
+
76
+ # Calculate how many lines can fit in one segment
77
+ max_lines_per_segment = (height - 2 * margin) // line_height
78
+
79
+ # Calculate number of segments needed
80
+ num_segments = math.ceil(len(lines) / max_lines_per_segment)
81
+
82
+ # Create segments
83
+ segments = []
84
+ current_line = 0
85
+
86
+ for i in range(num_segments):
87
+ segment_img, current_line = create_text_segment(
88
+ lines, current_line, max_lines_per_segment,
89
+ width, height, bg_color, text_color, font, align, margin
90
+ )
91
+ segments.append(segment_img)
92
+
93
+ # Combine all segments vertically
94
+ total_height = len(segments) * height
95
+ final_image = Image.new("RGB", (width, total_height), color=bg_color)
96
+
97
+ for i, segment in enumerate(segments):
98
+ final_image.paste(segment, (0, i * height))
99
+
100
+ return final_image
101
+
102
+ def render_math_image(text, font_size, width, height, bg_color, text_color):
103
+ bg_color = parse_color(bg_color)
104
+ text_color = parse_color(text_color)
105
+
106
+ fig, ax = plt.subplots(figsize=(width / 100, height / 100), facecolor=bg_color)
107
+ ax.set_facecolor(bg_color)
108
+ ax.axis('off')
109
+
110
+ if not (text.startswith(r"$") and text.endswith(r"$")):
111
+ text = rf"${text}$"
112
+
113
+ ax.text(0.5, 0.5, text, fontsize=font_size, ha='center', va='center', color=text_color)
114
+
115
+ buf = BytesIO()
116
+ plt.savefig(buf, format='png', bbox_inches='tight', pad_inches=0)
117
+ plt.close(fig)
118
+
119
+ buf.seek(0)
120
+ img = Image.open(buf)
121
+ return img
122
+
123
+ def text_to_image(input_text, font_size, width, height, bg_color, text_color, mode, font_name, align, image_format):
124
+ if mode == "Plain Text":
125
+ img = render_plain_text_image(input_text, font_size, width, height, bg_color, text_color, font_name, align)
126
+ elif mode == "LaTeX Math":
127
+ img = render_math_image(input_text, font_size, width, height, bg_color, text_color)
128
+ else:
129
+ return "Invalid mode selected!"
130
+
131
+ return img
132
+
133
+ def handle_file_upload(file, font_size, width, height, bg_color, text_color, mode, font_name, align, image_format):
134
+ if file is not None:
135
+ file_path = file[0]
136
+ with open(file_path, "r", encoding="utf-8") as f:
137
+ text = f.read()
138
+ return text_to_image(text, font_size, width, height, bg_color, text_color, mode, font_name, align, image_format)
139
+ return "No file uploaded!"
140
+
141
+ font_list = get_system_fonts()
142
+ default_font = "DejaVuSans.ttf" if "DejaVuSans.ttf" in font_list else font_list[0]
143
+
144
+ with gr.Blocks() as demo:
145
+ gr.Markdown("# 🖼️ Text to Image Converter")
146
+
147
+ with gr.Row():
148
+ input_text = gr.Textbox(label="Enter Text", placeholder="Type or paste text here...", lines=5)
149
+ file_input = gr.File(label="Upload a Text File", type="filepath")
150
+
151
+ with gr.Row():
152
+ font_size = gr.Slider(10, 100, value=30, label="Font Size")
153
+ font_name = gr.Dropdown(choices=font_list, value=default_font, label="Font")
154
+ align = gr.Radio(["Left", "Center", "Right"], label="Text Alignment", value="Center")
155
+
156
+ with gr.Row():
157
+ width = gr.Slider(200, 2000, value=800, label="Image Width")
158
+ height = gr.Slider(200, 2000, value=600, label="Base Height")
159
+
160
+ with gr.Row():
161
+ bg_color = gr.ColorPicker(label="Background Color", value="#FFFFFF")
162
+ text_color = gr.ColorPicker(label="Text Color", value="#000000")
163
+
164
+ with gr.Row():
165
+ mode = gr.Radio(["Plain Text", "LaTeX Math"], label="Rendering Mode", value="Plain Text")
166
+ image_format = gr.Radio(["PNG", "JPEG"], label="Image Format", value="PNG")
167
+
168
+ output_image = gr.Image(label="Generated Image")
169
+
170
+ with gr.Row():
171
+ convert_button = gr.Button("Convert Text to Image")
172
+ file_convert_button = gr.Button("Convert File to Image")
173
+
174
+ convert_button.click(
175
+ text_to_image,
176
+ inputs=[
177
+ input_text, font_size, width, height, bg_color, text_color,
178
+ mode, font_name, align, image_format
179
+ ],
180
+ outputs=output_image
181
+ )
182
+
183
+ file_convert_button.click(
184
+ handle_file_upload,
185
+ inputs=[
186
+ file_input, font_size, width, height, bg_color, text_color,
187
+ mode, font_name, align, image_format
188
+ ],
189
+ outputs=output_image
190
+ )
191
+
192
+ demo.launch()