ArrcttacsrjksX commited on
Commit
4e763f3
·
verified ·
1 Parent(s): 65c7b42

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +97 -106
app.py CHANGED
@@ -6,57 +6,55 @@ 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)
@@ -64,82 +62,43 @@ def render_plain_text_image(text, font_size, width, height, bg_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")
@@ -164,8 +123,26 @@ with gr.Blocks() as demo:
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")
@@ -175,18 +152,32 @@ with gr.Blocks() as demo:
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()
 
6
  import os
7
  import matplotlib
8
  import math
9
+ import tempfile
10
+ from pathlib import Path
11
+
12
+ # Thêm các font phổ biến
13
+ COMMON_FONTS = [
14
+ "Times New Roman",
15
+ "Arial",
16
+ "Calibri",
17
+ "Helvetica",
18
+ "Verdana",
19
+ "Tahoma",
20
+ "Georgia",
21
+ "Roboto",
22
+ "Open Sans",
23
+ "Segoe UI"
24
+ ]
25
 
26
  def get_system_fonts():
27
  fonts = []
28
+ common_fonts_found = []
29
+
30
+ # Lấy tất cả font trong hệ thống
31
  for font in matplotlib.font_manager.findSystemFonts(fontpaths=None, fontext='ttf'):
32
  font_name = os.path.basename(font)
33
+ actual_name = matplotlib.font_manager.FontProperties(fname=font).get_name()
34
+
35
+ # Kiểm tra nếu là font phổ biến
36
+ if any(common_font.lower() in actual_name.lower() for common_font in COMMON_FONTS):
37
+ common_fonts_found.append((font_name, font))
38
+ fonts.append((font_name, font))
 
 
 
 
 
 
 
39
 
40
+ # Sắp xếp để font phổ biến lên đầu
41
+ sorted_fonts = sorted(common_fonts_found, key=lambda x: COMMON_FONTS.index(
42
+ next(cf for cf in COMMON_FONTS if cf.lower() in matplotlib.font_manager.FontProperties(fname=x[1]).get_name().lower())
43
+ ))
44
+ sorted_fonts.extend([(f[0], f[1]) for f in fonts if f not in common_fonts_found])
45
 
46
+ return [f[0] for f in sorted_fonts], {f[0]: f[1] for f in sorted_fonts}
47
 
48
+ def save_image_to_file(img, format="PNG"):
49
+ # Tạo temporary file
50
+ temp_dir = Path(tempfile.gettempdir())
51
+ temp_file = temp_dir / f"text_image.{format.lower()}"
 
 
 
 
 
 
52
 
53
+ # Lưu ảnh
54
+ img.save(temp_file, format=format)
55
+ return str(temp_file)
56
+
57
+ [Previous functions remain the same: parse_color, calculate_text_dimensions, create_text_segment, render_math_image]
 
 
 
 
 
 
 
 
 
 
58
 
59
  def render_plain_text_image(text, font_size, width, height, bg_color, text_color, font_name, align):
60
  bg_color = parse_color(bg_color)
 
62
  margin = 10
63
 
64
  try:
65
+ font_path = FONT_PATHS.get(font_name, font_name)
66
  font = ImageFont.truetype(font_path, font_size)
67
  except Exception:
68
  font = ImageFont.load_default()
69
 
70
+ [Rest of the function remains the same]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
+ def text_to_image(input_text, font_size, width, height, bg_color, text_color,
73
+ mode, font_name, align, image_format, preview_mode):
 
 
 
 
 
 
 
74
  if mode == "Plain Text":
75
+ img = render_plain_text_image(input_text, font_size, width, height,
76
+ bg_color, text_color, font_name, align)
77
  elif mode == "LaTeX Math":
78
  img = render_math_image(input_text, font_size, width, height, bg_color, text_color)
79
  else:
80
  return "Invalid mode selected!"
81
 
82
+ if preview_mode:
83
+ return img
84
+ else:
85
+ # Return file path for download
86
+ return save_image_to_file(img, image_format)
87
 
88
+ def handle_file_upload(file, font_size, width, height, bg_color, text_color,
89
+ mode, font_name, align, image_format, preview_mode):
90
  if file is not None:
91
  file_path = file[0]
92
  with open(file_path, "r", encoding="utf-8") as f:
93
  text = f.read()
94
+ return text_to_image(text, font_size, width, height, bg_color, text_color,
95
+ mode, font_name, align, image_format, preview_mode)
96
  return "No file uploaded!"
97
 
98
+ # Get fonts and create font paths dictionary
99
+ font_list, FONT_PATHS = get_system_fonts()
100
+ default_font = next((f for f in font_list if "times" in f.lower()
101
+ or "arial" in f.lower()), font_list[0])
102
 
103
  with gr.Blocks() as demo:
104
  gr.Markdown("# 🖼️ Text to Image Converter")
 
123
  with gr.Row():
124
  mode = gr.Radio(["Plain Text", "LaTeX Math"], label="Rendering Mode", value="Plain Text")
125
  image_format = gr.Radio(["PNG", "JPEG"], label="Image Format", value="PNG")
126
+ preview_mode = gr.Checkbox(label="Preview Mode", value=True,
127
+ info="Uncheck to get download link instead of preview")
128
+
129
+ output = gr.Variable()
130
+ preview_image = gr.Image(label="Preview", visible=True)
131
+ download_link = gr.File(label="Download Image", visible=False)
132
+
133
+ def update_output(result, preview_mode):
134
+ if preview_mode:
135
+ return {
136
+ preview_image: result,
137
+ download_link: gr.update(visible=False),
138
+ preview_image: gr.update(visible=True)
139
+ }
140
+ else:
141
+ return {
142
+ download_link: result,
143
+ preview_image: gr.update(visible=False),
144
+ download_link: gr.update(visible=True)
145
+ }
146
 
147
  with gr.Row():
148
  convert_button = gr.Button("Convert Text to Image")
 
152
  text_to_image,
153
  inputs=[
154
  input_text, font_size, width, height, bg_color, text_color,
155
+ mode, font_name, align, image_format, preview_mode
156
  ],
157
+ outputs=[output]
158
+ ).then(
159
+ update_output,
160
+ inputs=[output, preview_mode],
161
+ outputs=[preview_image, download_link]
162
  )
163
 
164
  file_convert_button.click(
165
  handle_file_upload,
166
  inputs=[
167
  file_input, font_size, width, height, bg_color, text_color,
168
+ mode, font_name, align, image_format, preview_mode
169
  ],
170
+ outputs=[output]
171
+ ).then(
172
+ update_output,
173
+ inputs=[output, preview_mode],
174
+ outputs=[preview_image, download_link]
175
+ )
176
+
177
+ preview_mode.change(
178
+ update_output,
179
+ inputs=[output, preview_mode],
180
+ outputs=[preview_image, download_link]
181
  )
182
 
183
  demo.launch()