import gradio as gr import subprocess import json import os import stat import zipfile from PIL import ImageFont import matplotlib.font_manager # Path to the compiled engine executable ENGINE_EXECUTABLE = "./engine" def ensure_executable(file_path): """ Đảm bảo rằng file có quyền thực thi. Nếu không, cấp quyền thực thi. """ if not os.access(file_path, os.X_OK): # Kiểm tra quyền thực thi try: # Cấp quyền thực thi current_permissions = os.stat(file_path).st_mode os.chmod(file_path, current_permissions | stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH) print(f"Granted execute permission to {file_path}") except Exception as e: raise PermissionError(f"Failed to grant execute permission to {file_path}: {e}") def extract_and_load_fonts_from_directory(directory="fontfile", extract_to="extracted_fonts"): if not os.path.exists(extract_to): os.makedirs(extract_to) fonts = [] # Extract fonts from zip files for root, dirs, 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) print(f"Extracted: {zip_path}") except Exception as e: print(f"Failed to extract {zip_path}: {e}") # Collect all .ttf and .shx fonts for root, dirs, files in os.walk(extract_to): for file in files: if file.endswith(".ttf") or file.endswith(".shx"): fonts.append(os.path.join(root, file)) return fonts def get_system_fonts(): fonts = [] for font in matplotlib.font_manager.findSystemFonts(fontpaths=None, fontext='ttf'): fonts.append(font) return fonts def get_available_fonts(): # Get system fonts system_fonts = get_system_fonts() # Extract and load custom fonts extracted_fonts = extract_and_load_fonts_from_directory() # Combine and deduplicate fonts all_fonts = list(set(system_fonts + extracted_fonts)) return sorted(all_fonts) def call_engine(input_text, font_size, width, height, bg_color, text_color, mode, font_name, align, line_spacing, image_format): # Ensure the engine file is executable ensure_executable(ENGINE_EXECUTABLE) # Prepare input data as a dictionary 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, # Pass the selected font path "align": align, "line_spacing": line_spacing, "image_format": image_format } # Call the engine executable with input data result = subprocess.run( [ENGINE_EXECUTABLE, json.dumps(input_data)], capture_output=True, text=True ) # Handle errors if result.returncode != 0: raise Exception(f"Engine failed with error: {result.stderr}") # Get the output image path from stdout output_path = result.stdout.strip() # Load the generated image if os.path.exists(output_path): return output_path else: raise Exception("Failed to generate image!") 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...", lines=5) file_input = gr.File(label="Upload a Text File", type="filepath") with gr.Row(): font_size = gr.Slider(10, 100, value=30, label="Font Size") # Lấy danh sách font và đặt font mặc định là font đầu tiên available_fonts = get_available_fonts() default_font = available_fonts[0] if available_fonts else "" font_name = gr.Dropdown(choices=available_fonts, 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="Base 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") # Add line spacing slider line_spacing = gr.Slider(1.0, 3.0, value=1.2, step=0.1, label="Line Spacing") 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( call_engine, inputs=[ input_text, font_size, width, height, bg_color, text_color, mode, font_name, align, line_spacing, image_format ], outputs=output_image ) demo.launch()