Spaces:
Sleeping
Sleeping
import os | |
from pyppeteer import launch | |
from PIL import Image | |
import json | |
import random | |
from pydantic import BaseModel | |
from fastapi import FastAPI, HTTPException | |
import io | |
from fastapi.responses import StreamingResponse | |
app = FastAPI() | |
class HtmlInput(BaseModel): | |
message: str | |
async def convert_html_to_image(html, output_file, width=650, height=800, device_scale_factor=2): | |
try: | |
browser = await launch({ | |
'headless': True, | |
'args': ['--no-sandbox', '--disable-setuid-sandbox'], | |
'timeout': 60000 # Increase timeout if needed | |
}) | |
page = await browser.newPage() | |
await page.setViewport({'width': width, 'height': height, 'deviceScaleFactor': device_scale_factor}) | |
await page.setContent(html) | |
await page.screenshot({'path': output_file}) | |
await browser.close() | |
return output_file # Return the path of the captured image | |
except Exception as e: | |
print(f"Error in convert_html_to_image: {e}") | |
raise | |
async def optimize_image(input_file, output_file, target_size_kb=700): | |
# Open the image using PIL | |
with Image.open(input_file) as img: | |
# Calculate the initial quality to achieve the target size | |
quality = 95 | |
temp_output_file = output_file + ".temp.jpg" | |
img.save(temp_output_file, format='JPEG', quality=quality, optimize=True) | |
while os.path.getsize(temp_output_file) > target_size_kb * 1024 and quality > 0: | |
# Reduce the quality and save to temporary file | |
quality -= 5 | |
img.save(temp_output_file, format='JPEG', quality=quality, optimize=True) | |
# Save the optimized image to the output file | |
os.replace(temp_output_file, output_file) | |
async def mainFunction(html_content:str): | |
output_image_file = "image.jpg" | |
captured_image_path = await convert_html_to_image(html_content, output_image_file) | |
# Optimize the image to be less than 200KB | |
await optimize_image(captured_image_path, output_image_file) | |
return output_image_file | |
# Run the asynchronous main function | |
async def convert_html_to_image_endpoint(html_content:HtmlInput): | |
image_path = await mainFunction(html_content.message) | |
# Check if image was generated | |
if not image_path or not os.path.exists(image_path): | |
raise HTTPException(status_code=500, detail="Image generation failed.") | |
# Open the image file for streaming | |
with open(image_path, "rb") as img_file: | |
buffer = io.BytesIO(img_file.read()) | |
buffer.seek(0) | |
# Return the image as a downloadable file | |
return StreamingResponse(buffer, media_type="image/jpeg", headers={ | |
"Content-Disposition": f"attachment; filename={os.path.basename(image_path)}" | |
}) |