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/[email protected]/dist/katex.min.css"> | |
<script src="https://cdn.jsdelivr.net/npm/[email protected]/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 |