import os
from pyppeteer import launch
from PIL import Image
import json
import random
from pydantic import BaseModel
from fastapi import FastAPI
from jinja2 import Environment, FileSystemLoader
import io
app = FastAPI()
class HtmlInput(BaseModel):
message: str
async def convert_html_to_image(html, output_file, width=612, height=800, device_scale_factor=2):
browser = await launch(
headless=True,
args=[
'--no-sandbox',
'--disable-setuid-sandbox',
'--disable-gpu',
'--disable-dev-shm-usage', # Try to disable /dev/shm usage
'--disable-software-rasterizer',
'--disable-accelerated-2d-canvas',
'--disable-infobars',
'--disable-extensions',
'--disable-features=NetworkService',
'--disable-features=VizDisplayCompositor',
'--window-size=612,800'
]
)
page = await browser.newPage()
await page.setViewport({'width': width, 'height': height, 'deviceScaleFactor': device_scale_factor})
await page.setContent(html)
# Capture only the viewport without extra white space
await page.screenshot({'path': output_file})
await browser.close()
return output_file # Return the path of the captured image
# Function to tilt the content randomly
def tilt_content(html_content):
tilt_angle = random.randint(-3, 2) # Adjust the range of tilting angle as needed
tilted_content = f'
{html_content}
'
return tilted_content
def apply_random_css(html_content):
selected_css = random.choice([".txORqLQ { font-size: 13px; font-weight: bold; fill: #000080; color:#000080; }",
".txORqLQ { font-size: 12px; font-weight: bold; fill: #000080; color:#000080; }",
".txORqLQ { font: bold 10px 'Courier New',Courier,monospace; }",
".txORqLQ { font: bold 10.5px 'Courier New',Courier,monospace; }"])
offset_content=html_content
offset_content = f'' + offset_content
return offset_content
def apply_random_css_positioning(html_content):
selected_css = random.choice([".address { position: relative;bottom: 48.6rem;left: 16.8rem;width: 11rem; margin-top:0.3rem}",
".address { position: relative;bottom: 47.8rem;left: 10.9rem;width: 30rem; margin-top:0.3rem}"
])
offset_content=html_content
offset_content = f'' + offset_content
return offset_content
def apply_position_offset(html_content):
# Random offsets in x and y directions
offset_x = random.randint(-20, 20) # Adjust the range of x offset as needed
offset_y = random.randint(-20, 20) # Adjust the range of y offset as needed
# Apply the offsets to the content
offset_content = f'{html_content}
'
return offset_content
async def optimize_image(input_file, output_file, target_size_kb=200):
# 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):
print("in main function")
# Create img folder if not exists
if not os.path.exists('img'):
os.makedirs('img')
if not os.path.exists('json'):
os.makedirs('json')
# Write the HTML string to the file
html_file = io.StringIO(html_content)
print("html file created")
template_loader = FileSystemLoader(searchpath=".")
template_env = Environment(loader=template_loader)
template = template_env.from_string(html_file.getvalue())
print("Template rendered successfully")
# Load JSON data from files
with open("modified_data.json", "r", encoding="utf-8") as universal_file:
universal_json_data = json.load(universal_file)
# Define the start number
start_number = 17800
# Loop over each record in the universal JSON
for index, record in enumerate(universal_json_data):
# Increment index by start_number
index += start_number
# Generate json file
# Load the template
json_output_file = os.path.join('json', f"{index:05d}.json")
with open(json_output_file, "w", encoding="utf-8") as json_file:
json.dump(record, json_file, indent=4, ensure_ascii=False)
html_output = template.render(record)
html_output= apply_random_css(html_output)
html_output=apply_random_css_positioning(html_output)
# Apply random position offset
# html_output = apply_position_offset(html_output)
# Tilt the content randomly
# html_output = tilt_content(html_output)
# Convert HTML to image
output_image_file = os.path.join('img', f"{index:05d}.jpg")
captured_image_path = await convert_html_to_image(html_output, output_image_file)
# Optimize the image to be less than 200KB
await optimize_image(captured_image_path, output_image_file)
# Run the asynchronous main function
@app.post("/convert-html-to-image/")
async def convert_html_to_image_endpoint(html_content:HtmlInput):
await mainFunction(html_content.message)