Spaces:
Running
Running
import gradio as gr | |
import subprocess | |
import json | |
import os | |
import stat | |
import requests | |
import datetime | |
import zipfile | |
import matplotlib.font_manager | |
from huggingface_hub import HfApi, HfFolder | |
# Hugging Face repo and token | |
HF_REPO = "ArrcttacsrjksX/Texttoimage" | |
HF_ENGINE_URL = "https://huggingface.co/ArrcttacsrjksX/Texttoimage/resolve/main/engine" | |
HF_TOKEN = os.getenv("HF_TOKEN") # Lấy token từ biến môi trường | |
ENGINE_EXECUTABLE = "./engine" | |
def download_engine(): | |
"""Download engine from Hugging Face if not available.""" | |
if not os.path.exists(ENGINE_EXECUTABLE): | |
headers = {"Authorization": f"Bearer {HF_TOKEN}"} | |
response = requests.get(HF_ENGINE_URL, headers=headers, stream=True) | |
if response.status_code == 200: | |
with open(ENGINE_EXECUTABLE, "wb") as f: | |
for chunk in response.iter_content(chunk_size=8192): | |
f.write(chunk) | |
os.chmod(ENGINE_EXECUTABLE, os.stat(ENGINE_EXECUTABLE).st_mode | stat.S_IXUSR) | |
else: | |
raise Exception("Failed to download engine") | |
def ensure_executable(file_path): | |
if not os.access(file_path, os.X_OK): | |
os.chmod(file_path, os.stat(file_path).st_mode | stat.S_IXUSR) | |
def extract_and_load_fonts(directory="fontfile", extract_to="extracted_fonts"): | |
if not os.path.exists(extract_to): | |
os.makedirs(extract_to) | |
fonts = [] | |
for root, _, files in os.walk(directory): | |
for file in files: | |
if file.endswith(".zip"): | |
zip_path = os.path.join(root, file) | |
try: | |
with zipfile.ZipFile(zip_path, 'r') as zip_ref: | |
zip_ref.extractall(extract_to) | |
except Exception as e: | |
print(f"Failed to extract {zip_path}: {e}") | |
for root, _, files in os.walk(extract_to): | |
for file in files: | |
if file.endswith(".ttf") or file.endswith(".otf") or file.endswith(".shx"): | |
fonts.append(os.path.join(root, file)) | |
return fonts | |
def get_system_fonts(): | |
return matplotlib.font_manager.findSystemFonts(fontpaths=None, fontext='ttf') | |
def get_available_fonts(): | |
system_fonts = get_system_fonts() | |
extracted_fonts = extract_and_load_fonts() | |
return sorted(set(system_fonts + extracted_fonts)) | |
def upload_to_huggingface(file_path, text_content, timestamp_folder): | |
"""Upload image and text to Hugging Face repo.""" | |
api = HfApi() | |
HfFolder.save_token(HF_TOKEN) | |
repo_path = f"{HF_REPO}/{timestamp_folder}" | |
api.upload_file(path_or_fileobj=file_path, path_in_repo=f"{repo_path}/image.png", repo_id=HF_REPO) | |
with open("temp_text.txt", "w") as f: | |
f.write(text_content) | |
api.upload_file(path_or_fileobj="temp_text.txt", path_in_repo=f"{repo_path}/text.txt", repo_id=HF_REPO) | |
os.remove("temp_text.txt") | |
def call_engine(file_input, input_text, font_size, width, height, bg_color, text_color, mode, font_name, align, line_spacing, image_format): | |
download_engine() | |
ensure_executable(ENGINE_EXECUTABLE) | |
if file_input: | |
input_text = read_file_content(file_input) | |
input_data = { | |
"input_text": input_text, | |
"font_size": font_size, | |
"width": width, | |
"height": height, | |
"bg_color": bg_color, | |
"text_color": text_color, | |
"mode": mode, | |
"font_path": font_name, | |
"align": align, | |
"line_spacing": line_spacing, | |
"image_format": image_format | |
} | |
result = subprocess.run([ENGINE_EXECUTABLE, json.dumps(input_data)], capture_output=True, text=True) | |
if result.returncode != 0: | |
raise Exception(f"Engine error: {result.stderr}") | |
output_path = result.stdout.strip() | |
timestamp_folder = datetime.datetime.now().strftime("%d-%m-%Y %H-%M-%S") | |
upload_to_huggingface(output_path, input_text, timestamp_folder) | |
return output_path | |
def read_file_content(file): | |
"""Read text from uploaded file.""" | |
try: | |
return file.decode("utf-8") if isinstance(file, bytes) else file.read().decode("utf-8") | |
except Exception as e: | |
return f"Error reading file: {e}" | |
with gr.Blocks() as demo: | |
gr.Markdown("# 🖼️ Text to Image Converter") | |
available_fonts = get_available_fonts() | |
default_font = available_fonts[0] if available_fonts else "" | |
with gr.Row(): | |
input_text = gr.Textbox(label="Enter Text", placeholder="Type or paste text here...", lines=5) | |
file_input = gr.File(label="Upload a Text File", type="binary") | |
with gr.Row(): | |
font_size = gr.Slider(0, 510, value=30, label="Font Size") | |
font_name = gr.Dropdown(choices=available_fonts, value=default_font, label="Font") | |
align = gr.Radio(["Left", "Center", "Right"], label="Text Alignment", value="Center") | |
width = gr.Slider(0, 9000, value=800, label="Image Width") | |
height = gr.Slider(0, 9000, 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") | |
line_spacing = gr.Slider(1.0, 1000.0, value=1.2, step=0.1, label="Line Spacing") | |
output_image = gr.Image(label="Generated Image") | |
convert_button = gr.Button("Convert Text to Image") | |
convert_button.click( | |
call_engine, | |
inputs=[file_input, input_text, font_size, width, height, bg_color, text_color, mode, font_name, align, line_spacing, image_format], | |
outputs=output_image | |
) | |
demo.launch() | |