| import time | |
| import base64 | |
| import io | |
| from PIL import Image | |
| from bs4 import BeautifulSoup | |
| from langchain_google_genai import ChatGoogleGenerativeAI | |
| from langchain_core.messages import HumanMessage | |
| def resize_and_encode_image(image_file, max_size=(400, 400)): | |
| img = Image.open(image_file) | |
| img.thumbnail(max_size) | |
| buffered = io.BytesIO() | |
| img.save(buffered, format="JPEG") | |
| image_bytes = buffered.getvalue() | |
| base64_str = base64.b64encode(image_bytes).decode("utf-8") | |
| return f"data:image/jpeg;base64,{base64_str}" | |
| def beautify_html(html_code): | |
| soup = BeautifulSoup(html_code, "html.parser") | |
| return soup.prettify() | |
| def generate_html_css_from_image(image_file): | |
| image_data_url = resize_and_encode_image(image_file) | |
| prompt_text = """ | |
| You are an expert front-end developer. | |
| The input is a screenshot of a website UI. Carefully analyze its layout and generate accurate, semantic, and maintainable HTML and CSS. | |
| Follow these professional guidelines: | |
| 1) Structure & Semantics: | |
| - Use HTML5 semantic tags that match the visual hierarchy (e.g., <header>, <nav>, <main>, <section>, <article>, <aside>, <footer>) | |
| - Reflect layout grouping using appropriate containers and divs where needed | |
| 2) Layout & Responsiveness: | |
| - Use Flexbox or CSS Grid for layout | |
| - Include responsive breakpoints (mobile-first) with at least one media query | |
| - Ensure layout adapts well to mobile screen sizes | |
| 3) CSS Practices: | |
| - Keep CSS in a <style> block or separate file (no inline styles) | |
| - Use class names that follow a clean naming convention (e.g., BEM or descriptive naming) | |
| - Group CSS rules logically (layout, typography, components) | |
| 4) Accessibility & UX: | |
| - Add accessible markup: alt text, ARIA roles, labels | |
| - Ensure good contrast and keyboard navigability | |
| 5) Content & Comments: | |
| - Use meaningful placeholder text (not lorem ipsum) | |
| - Add short code comments to explain each major section | |
| 6) Output: | |
| - The output should be a complete single HTML file with embedded CSS | |
| - Preserve the visual structure and content flow of the original screenshot as closely as possible | |
| - Do not skip or summarize any sections | |
| Assume this is for real production-ready front-end code generation from a web UI screenshot. | |
| """ | |
| prompt = [ | |
| HumanMessage( | |
| content=[ | |
| {"type": "text", "text": prompt_text}, | |
| {"type": "image_url", "image_url": {"url": image_data_url, "mime_type": "image/jpeg"}} | |
| ] | |
| ) | |
| ] | |
| llm = ChatGoogleGenerativeAI(model="gemini-2.5-flash", temperature=0) | |
| max_retries = 3 | |
| generated_code = None | |
| for attempt in range(max_retries): | |
| try: | |
| response = llm.invoke(prompt) | |
| generated_code = response.content | |
| break | |
| except Exception as e: | |
| if "ResourceExhausted" in str(e) or "429" in str(e): | |
| time.sleep(30 * (attempt + 1)) | |
| else: | |
| raise e | |
| if generated_code: | |
| soup = BeautifulSoup(generated_code, "html.parser") | |
| style_tag = soup.find("style") | |
| css_code = style_tag.string if style_tag else "" | |
| html_without_style = str(soup).replace(str(style_tag), "") if style_tag else str(soup) | |
| cleaned_html = beautify_html(html_without_style) | |
| final_output = f"""<!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> | |
| <style> | |
| {css_code} | |
| </style> | |
| </head> | |
| {cleaned_html.split("</head>")[1]} | |
| </html>""" | |
| return final_output | |
| else: | |
| return None | |