import subprocess import sys import os import json import uuid import shutil from PIL import Image from pathlib import Path # This function is now more robust, injecting the prompt into a temporary copy of the generator. def inject_prompt_to_generator(prompt_text, temp_generator_path): if not prompt_text: return user_instruction = { "sidebar": "Make all icons look better; fill in relevant English text; beautify the layout.", "header": "Make the Google logo look better; change the avatar color to be more appealing.", "navigation": "Please beautify the layout.", "main content": prompt_text } with open(temp_generator_path, 'r', encoding='utf-8') as f: content = f.read() start_marker = "user_instruction = {" end_marker = "}" start_index = content.find(start_marker) end_index = content.find(end_marker, start_index) if start_index != -1 and end_index != -1: dict_str = f"user_instruction = {json.dumps(user_instruction, indent=4)}" content = content[:start_index] + dict_str + content[end_index+1:] with open(temp_generator_path, 'w', encoding='utf-8') as f: f.write(content) def run_script_with_run_id(script_name, run_id, instructions=None): """Executes a script with a specific run_id and optional instructions.""" # HF Spaces: Use absolute paths based on the script's location screencoder_dir = Path(__file__).parent.resolve() script_path = screencoder_dir / script_name if not script_path.exists(): # Handle scripts inside subdirectories like UIED/ script_path = screencoder_dir / "UIED" / script_name command = [sys.executable, str(script_path), "--run_id", run_id] # Add instructions to the command if provided if instructions and "html_generator.py" in str(script_path): instructions_json = json.dumps(instructions) command.extend(["--instructions", instructions_json]) print(f"\n--- Running script: {script_path.name} ---") try: # Pass the current environment variables to the subprocess result = subprocess.run(command, check=True, capture_output=True, text=True, env=os.environ) print(result.stdout) if result.stderr: print("Error:") print(result.stderr) except subprocess.CalledProcessError as e: print(f"Error executing {script_path.name}:") print(e.stdout) print(e.stderr) raise # Re-raise the exception to stop the workflow if a script fails def generate_html_for_demo(image_path, instructions): """ A refactored main function for Gradio demo integration. It orchestrates the script executions for a single image processing run. - Creates a unique run_id for each call. - Sets up temporary directories for input and output. - Cleans up temporary directories after execution. """ run_id = str(uuid.uuid4()) print(f"--- Starting Screencoder workflow for run_id: {run_id} ---") # HF Spaces: Use absolute paths and pathlib for robustness base_dir = Path(__file__).parent.resolve() tmp_dir = base_dir / 'data' / 'tmp' / run_id output_dir = base_dir / 'data' / 'output' / run_id os.makedirs(tmp_dir, exist_ok=True) os.makedirs(output_dir, exist_ok=True) try: # 1. Copy user-uploaded image to the temp input directory new_image_path = tmp_dir / f"{run_id}.png" img = Image.open(image_path) img.save(new_image_path, "PNG") # 2. Run the processing scripts in sequence run_script_with_run_id("UIED/run_single.py", run_id) run_script_with_run_id("block_parsor.py", run_id) run_script_with_run_id("html_generator.py", run_id, instructions) run_script_with_run_id("image_box_detection.py", run_id) run_script_with_run_id("mapping.py", run_id) run_script_with_run_id("image_replacer.py", run_id) # 3. Read the final generated HTML final_html_path = output_dir / f"{run_id}_layout_final.html" if final_html_path.exists(): with open(final_html_path, 'r', encoding='utf-8') as f: html_content = f.read() print(f"Successfully generated HTML for run_id: {run_id}") return html_content, run_id else: error_msg = f"Error: Final HTML file not found for run_id: {run_id}" return error_msg, run_id except Exception as e: error_msg = f"An error occurred: {e}" print(f"An error occurred during the workflow for run_id {run_id}: {e}") return error_msg, run_id finally: # 4. Cleanup: Remove temporary directories try: # shutil.rmtree(tmp_dir) # shutil.rmtree(output_dir) print(f"Cleaned up temporary files for run_id: {run_id}") except OSError as e: print(f"Error cleaning up temporary files for run_id {run_id}: {e}") def main(): """Main function to run the entire Screencoder workflow (legacy).""" print("Starting the Screencoder full workflow (legacy)...") # This main function is now considered legacy and should not be used in HF Spaces. run_id = "test1" # Hardcoded for legacy main # Use a dummy image path for legacy run dummy_image_path = Path(__file__).parent.resolve() / "data" / "input" / "test1.png" instructions = {"main content": "Generate the HTML for this screenshot."} generate_html_for_demo(str(dummy_image_path), instructions) print("\nScreencoder workflow completed successfully!") if __name__ == "__main__": main()