ArrcttacsrjksX commited on
Commit
5bf065f
·
verified ·
1 Parent(s): bd8e0cc

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +84 -78
app.py CHANGED
@@ -3,87 +3,75 @@ import subprocess
3
  import json
4
  import os
5
  import stat
6
- import requests
7
- import datetime
8
  import zipfile
 
9
  import matplotlib.font_manager
10
- from huggingface_hub import HfApi, HfFolder
11
- from matplotlib.colors import to_rgba
12
 
13
- # Hugging Face repo and token
14
- HF_REPO = "ArrcttacsrjksX/Texttoimage"
15
- HF_ENGINE_URL = "https://huggingface.co/ArrcttacsrjksX/Texttoimage/resolve/main/engine"
16
- HF_TOKEN = os.getenv("HF_TOKEN") # Lấy token từ biến môi trường
17
  ENGINE_EXECUTABLE = "./engine"
18
 
19
- def download_engine():
20
- """Download engine from Hugging Face if not available."""
21
- if not os.path.exists(ENGINE_EXECUTABLE):
22
- headers = {"Authorization": f"Bearer {HF_TOKEN}"}
23
- response = requests.get(HF_ENGINE_URL, headers=headers, stream=True)
24
- if response.status_code == 200:
25
- with open(ENGINE_EXECUTABLE, "wb") as f:
26
- for chunk in response.iter_content(chunk_size=8192):
27
- f.write(chunk)
28
- os.chmod(ENGINE_EXECUTABLE, os.stat(ENGINE_EXECUTABLE).st_mode | stat.S_IXUSR)
29
- else:
30
- raise Exception("Failed to download engine")
31
-
32
  def ensure_executable(file_path):
33
- if not os.access(file_path, os.X_OK):
34
- os.chmod(file_path, os.stat(file_path).st_mode | stat.S_IXUSR)
 
 
 
 
 
 
 
 
 
 
35
 
36
- def extract_and_load_fonts(directory="fontfile", extract_to="extracted_fonts"):
37
  if not os.path.exists(extract_to):
38
  os.makedirs(extract_to)
 
39
  fonts = []
40
- for root, _, files in os.walk(directory):
 
 
41
  for file in files:
42
  if file.endswith(".zip"):
43
  zip_path = os.path.join(root, file)
44
  try:
45
  with zipfile.ZipFile(zip_path, 'r') as zip_ref:
46
  zip_ref.extractall(extract_to)
 
47
  except Exception as e:
48
  print(f"Failed to extract {zip_path}: {e}")
49
- for root, _, files in os.walk(extract_to):
 
 
50
  for file in files:
51
- if file.endswith(".ttf") or file.endswith(".otf") or file.endswith(".shx"):
52
  fonts.append(os.path.join(root, file))
 
53
  return fonts
54
 
55
  def get_system_fonts():
56
- return matplotlib.font_manager.findSystemFonts(fontpaths=None, fontext='ttf')
 
 
 
57
 
58
  def get_available_fonts():
 
59
  system_fonts = get_system_fonts()
60
- extracted_fonts = extract_and_load_fonts()
61
- return sorted(set(system_fonts + extracted_fonts))
62
-
63
- def upload_to_huggingface(file_path, text_content, timestamp_folder):
64
- """Upload image and text to Hugging Face repo."""
65
- api = HfApi()
66
- HfFolder.save_token(HF_TOKEN)
67
- repo_path = f"{HF_REPO}/{timestamp_folder}"
68
- api.upload_file(path_or_fileobj=file_path, path_in_repo=f"{repo_path}/image.png", repo_id=HF_REPO)
69
- with open("temp_text.txt", "w") as f:
70
- f.write(text_content)
71
- api.upload_file(path_or_fileobj="temp_text.txt", path_in_repo=f"{repo_path}/text.txt", repo_id=HF_REPO)
72
- os.remove("temp_text.txt")
73
-
74
- def call_engine(file_input, input_text, font_size, width, height, bg_color, text_color, mode, font_name, align, line_spacing, image_format):
75
- download_engine()
76
- ensure_executable(ENGINE_EXECUTABLE)
77
- if file_input:
78
- input_text = read_file_content(file_input)
79
 
80
- # Chuyển đổi màu sắc sang dạng hợp lệ
81
- try:
82
- bg_color = to_rgba(bg_color)[:3] # Chuyển đổi thành tuple (R, G, B)
83
- text_color = to_rgba(text_color)[:3] # Chuyển đổi thành tuple (R, G, B)
84
- except ValueError:
85
- raise Exception("Invalid color format. Please use a valid color code or tuple.")
86
 
 
 
 
 
 
 
 
 
 
87
  input_data = {
88
  "input_text": input_text,
89
  "font_size": font_size,
@@ -92,58 +80,76 @@ def call_engine(file_input, input_text, font_size, width, height, bg_color, text
92
  "bg_color": bg_color,
93
  "text_color": text_color,
94
  "mode": mode,
95
- "font_path": font_name,
96
  "align": align,
97
  "line_spacing": line_spacing,
98
  "image_format": image_format
99
  }
100
- result = subprocess.run([ENGINE_EXECUTABLE, json.dumps(input_data)], capture_output=True, text=True)
 
 
 
 
 
 
 
 
101
  if result.returncode != 0:
102
- raise Exception(f"Engine error: {result.stderr}")
 
 
103
  output_path = result.stdout.strip()
104
- timestamp_folder = datetime.datetime.now().strftime("%d-%m-%Y %H-%M-%S")
105
- upload_to_huggingface(output_path, input_text, timestamp_folder)
106
- return output_path
107
 
108
- def read_file_content(file):
109
- """Read text from uploaded file."""
110
- try:
111
- return file.decode("utf-8") if isinstance(file, bytes) else file.read().decode("utf-8")
112
- except Exception as e:
113
- return f"Error reading file: {e}"
114
 
115
  with gr.Blocks() as demo:
116
  gr.Markdown("# 🖼️ Text to Image Converter")
117
- available_fonts = get_available_fonts()
118
- default_font = available_fonts[0] if available_fonts else ""
119
-
120
  with gr.Row():
121
  input_text = gr.Textbox(label="Enter Text", placeholder="Type or paste text here...", lines=5)
122
- file_input = gr.File(label="Upload a Text File", type="binary")
123
-
124
  with gr.Row():
125
  font_size = gr.Slider(10, 100, value=30, label="Font Size")
 
 
 
 
 
126
  font_name = gr.Dropdown(choices=available_fonts, value=default_font, label="Font")
127
  align = gr.Radio(["Left", "Center", "Right"], label="Text Alignment", value="Center")
 
 
128
  width = gr.Slider(200, 2000, value=800, label="Image Width")
129
- height = gr.Slider(200, 2000, value=600, label="Image Height")
130
-
131
  with gr.Row():
132
  bg_color = gr.ColorPicker(label="Background Color", value="#FFFFFF")
133
  text_color = gr.ColorPicker(label="Text Color", value="#000000")
134
-
135
  with gr.Row():
136
  mode = gr.Radio(["Plain Text", "LaTeX Math"], label="Rendering Mode", value="Plain Text")
137
  image_format = gr.Radio(["PNG", "JPEG"], label="Image Format", value="PNG")
138
-
 
139
  line_spacing = gr.Slider(1.0, 3.0, value=1.2, step=0.1, label="Line Spacing")
 
140
  output_image = gr.Image(label="Generated Image")
141
-
142
- convert_button = gr.Button("Convert Text to Image")
143
-
 
 
144
  convert_button.click(
145
  call_engine,
146
- inputs=[file_input, input_text, font_size, width, height, bg_color, text_color, mode, font_name, align, line_spacing, image_format],
 
 
 
147
  outputs=output_image
148
  )
149
 
 
3
  import json
4
  import os
5
  import stat
 
 
6
  import zipfile
7
+ from PIL import ImageFont
8
  import matplotlib.font_manager
 
 
9
 
10
+ # Path to the compiled engine executable
 
 
 
11
  ENGINE_EXECUTABLE = "./engine"
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  def ensure_executable(file_path):
14
+ """
15
+ Đảm bảo rằng file có quyền thực thi.
16
+ Nếu không, cấp quyền thực thi.
17
+ """
18
+ if not os.access(file_path, os.X_OK): # Kiểm tra quyền thực thi
19
+ try:
20
+ # Cấp quyền thực thi
21
+ current_permissions = os.stat(file_path).st_mode
22
+ os.chmod(file_path, current_permissions | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH)
23
+ print(f"Granted execute permission to {file_path}")
24
+ except Exception as e:
25
+ raise PermissionError(f"Failed to grant execute permission to {file_path}: {e}")
26
 
27
+ def extract_and_load_fonts_from_directory(directory="fontfile", extract_to="extracted_fonts"):
28
  if not os.path.exists(extract_to):
29
  os.makedirs(extract_to)
30
+
31
  fonts = []
32
+
33
+ # Extract fonts from zip files
34
+ for root, dirs, files in os.walk(directory):
35
  for file in files:
36
  if file.endswith(".zip"):
37
  zip_path = os.path.join(root, file)
38
  try:
39
  with zipfile.ZipFile(zip_path, 'r') as zip_ref:
40
  zip_ref.extractall(extract_to)
41
+ print(f"Extracted: {zip_path}")
42
  except Exception as e:
43
  print(f"Failed to extract {zip_path}: {e}")
44
+
45
+ # Collect all .ttf and .shx fonts
46
+ for root, dirs, files in os.walk(extract_to):
47
  for file in files:
48
+ if file.endswith(".ttf") or file.endswith(".shx"):
49
  fonts.append(os.path.join(root, file))
50
+
51
  return fonts
52
 
53
  def get_system_fonts():
54
+ fonts = []
55
+ for font in matplotlib.font_manager.findSystemFonts(fontpaths=None, fontext='ttf'):
56
+ fonts.append(font)
57
+ return fonts
58
 
59
  def get_available_fonts():
60
+ # Get system fonts
61
  system_fonts = get_system_fonts()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
 
63
+ # Extract and load custom fonts
64
+ extracted_fonts = extract_and_load_fonts_from_directory()
 
 
 
 
65
 
66
+ # Combine and deduplicate fonts
67
+ all_fonts = list(set(system_fonts + extracted_fonts))
68
+ return sorted(all_fonts)
69
+
70
+ def call_engine(input_text, font_size, width, height, bg_color, text_color, mode, font_name, align, line_spacing, image_format):
71
+ # Ensure the engine file is executable
72
+ ensure_executable(ENGINE_EXECUTABLE)
73
+
74
+ # Prepare input data as a dictionary
75
  input_data = {
76
  "input_text": input_text,
77
  "font_size": font_size,
 
80
  "bg_color": bg_color,
81
  "text_color": text_color,
82
  "mode": mode,
83
+ "font_path": font_name, # Pass the selected font path
84
  "align": align,
85
  "line_spacing": line_spacing,
86
  "image_format": image_format
87
  }
88
+
89
+ # Call the engine executable with input data
90
+ result = subprocess.run(
91
+ [ENGINE_EXECUTABLE, json.dumps(input_data)],
92
+ capture_output=True,
93
+ text=True
94
+ )
95
+
96
+ # Handle errors
97
  if result.returncode != 0:
98
+ raise Exception(f"Engine failed with error: {result.stderr}")
99
+
100
+ # Get the output image path from stdout
101
  output_path = result.stdout.strip()
 
 
 
102
 
103
+ # Load the generated image
104
+ if os.path.exists(output_path):
105
+ return output_path
106
+ else:
107
+ raise Exception("Failed to generate image!")
 
108
 
109
  with gr.Blocks() as demo:
110
  gr.Markdown("# 🖼️ Text to Image Converter")
111
+
 
 
112
  with gr.Row():
113
  input_text = gr.Textbox(label="Enter Text", placeholder="Type or paste text here...", lines=5)
114
+ file_input = gr.File(label="Upload a Text File", type="filepath")
115
+
116
  with gr.Row():
117
  font_size = gr.Slider(10, 100, value=30, label="Font Size")
118
+
119
+ # Lấy danh sách font và đặt font mặc định là font đầu tiên
120
+ available_fonts = get_available_fonts()
121
+ default_font = available_fonts[0] if available_fonts else ""
122
+
123
  font_name = gr.Dropdown(choices=available_fonts, value=default_font, label="Font")
124
  align = gr.Radio(["Left", "Center", "Right"], label="Text Alignment", value="Center")
125
+
126
+ with gr.Row():
127
  width = gr.Slider(200, 2000, value=800, label="Image Width")
128
+ height = gr.Slider(200, 2000, value=600, label="Base Height")
129
+
130
  with gr.Row():
131
  bg_color = gr.ColorPicker(label="Background Color", value="#FFFFFF")
132
  text_color = gr.ColorPicker(label="Text Color", value="#000000")
133
+
134
  with gr.Row():
135
  mode = gr.Radio(["Plain Text", "LaTeX Math"], label="Rendering Mode", value="Plain Text")
136
  image_format = gr.Radio(["PNG", "JPEG"], label="Image Format", value="PNG")
137
+
138
+ # Add line spacing slider
139
  line_spacing = gr.Slider(1.0, 3.0, value=1.2, step=0.1, label="Line Spacing")
140
+
141
  output_image = gr.Image(label="Generated Image")
142
+
143
+ with gr.Row():
144
+ convert_button = gr.Button("Convert Text to Image")
145
+ file_convert_button = gr.Button("Convert File to Image")
146
+
147
  convert_button.click(
148
  call_engine,
149
+ inputs=[
150
+ input_text, font_size, width, height, bg_color, text_color,
151
+ mode, font_name, align, line_spacing, image_format
152
+ ],
153
  outputs=output_image
154
  )
155