Spaces:
Running
Running
| from playwright.sync_api import sync_playwright | |
| from PIL import Image | |
| import io | |
| def latex_to_pil(latex_code, target_width, target_height, fontsize=18): | |
| html_template = """ | |
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.13.0/dist/katex.min.css"> | |
| <script src="https://cdn.jsdelivr.net/npm/katex@0.12.0/dist/katex.min.js"></script> | |
| <style> | |
| body { | |
| margin: 0; | |
| padding: 0; | |
| display: flex; | |
| } | |
| #content { | |
| font-size: {fontsize}px; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div id="content">{content}</div> | |
| <script> | |
| function renderMath() { | |
| let content = document.getElementById('content'); | |
| let html = content.innerHTML; | |
| // Replace display equations | |
| html = html.replace(/\\$\\$(.*?)\\$\\$/gs, (match, equation) => { | |
| let span = document.createElement('span'); | |
| katex.render(equation, span, { displayMode: true, throwOnError: false, errorColor: '#000' }); | |
| return span.outerHTML; | |
| }); | |
| // Replace inline equations | |
| html = html.replace(/\\$(.*?)\\$/g, (match, equation) => { | |
| if(match.startsWith('\\\\$')) return match; // Ignore escaped dollars | |
| let span = document.createElement('span'); | |
| katex.render(equation, span, { displayMode: false, throwOnError: false, errorColor: '#000' }); | |
| return span.outerHTML; | |
| }); | |
| content.innerHTML = html; | |
| } | |
| renderMath(); | |
| </script> | |
| </body> | |
| </html> | |
| """ | |
| formatted_latex = latex_code.replace('\n', '\\n').replace('"', '\\"') | |
| with sync_playwright() as p: | |
| browser = p.chromium.launch() | |
| page = browser.new_page() | |
| page.set_viewport_size({'width': target_width, 'height': target_height}) | |
| while fontsize <= 30: | |
| html_content = html_template.replace("{content}", formatted_latex).replace("{fontsize}", str(fontsize)) | |
| page.set_content(html_content) | |
| dimensions = page.evaluate("""() => { | |
| const render = document.getElementById('content'); | |
| return { | |
| width: render.offsetWidth, | |
| height: render.offsetHeight | |
| }; | |
| }""") | |
| if dimensions['width'] >= target_width or dimensions['height'] >= target_height: | |
| fontsize -= 1 | |
| break | |
| else: | |
| fontsize += 1 | |
| html_content = html_template.replace("{content}", formatted_latex).replace("{fontsize}", str(fontsize)) | |
| page.set_content(html_content) | |
| screenshot_bytes = page.screenshot() | |
| browser.close() | |
| image_stream = io.BytesIO(screenshot_bytes) | |
| pil_image = Image.open(image_stream) | |
| pil_image.load() | |
| return pil_image |