Spaces:
Sleeping
Sleeping
| from fastapi import FastAPI, File, UploadFile | |
| from fastapi.responses import HTMLResponse | |
| import numpy as np | |
| from PIL import Image | |
| from io import BytesIO | |
| import requests | |
| import base64 | |
| import os | |
| app = FastAPI() | |
| # Function for cropping and filling the image | |
| def fill_square_cropper(img): | |
| imgsz = [img.height, img.width] | |
| avg_color_per_row = np.average(img, axis=0) | |
| avg_color = np.average(avg_color_per_row, axis=0) | |
| if img.height > img.width: | |
| newimg = Image.new( | |
| 'RGB', | |
| (img.height, img.height), | |
| (round(avg_color[0]), round(avg_color[1]), round(avg_color[2])) | |
| ) | |
| newpos = (img.height - img.width) // 2 | |
| newimg.paste(img, (newpos, 0)) | |
| return newimg | |
| elif img.width > img.height: | |
| newimg = Image.new( | |
| 'RGB', | |
| (img.width, img.width), | |
| (round(avg_color[0]), round(avg_color[1]), round(avg_color[2])) | |
| ) | |
| newpos = (img.width - img.height) // 2 | |
| newimg.paste(img, (0, newpos)) | |
| return newimg | |
| else: | |
| return img | |
| # Home Page | |
| def home_page(): | |
| return """ | |
| <html> | |
| <body> | |
| <h2>Square and Fill Image App</h2> | |
| <p>Select a option below:</p> | |
| <ul> | |
| <li><a href="/demo">Demo</a></li> | |
| <li><a href="/application">Application</a></li> | |
| </ul> | |
| </body> | |
| </html> | |
| """ | |
| # Demo Page | |
| def demo_page(): | |
| # URLs for demo images | |
| url1 = "https://raw.githubusercontent.com/webdevserv/images_video/main/cowportrait.jpg" | |
| url2 = "https://raw.githubusercontent.com/webdevserv/images_video/main/cowlandscape.jpg" | |
| # Process the first image | |
| response = requests.get(url1) | |
| img1 = Image.open(BytesIO(response.content)).convert("RGB") | |
| squared_img1 = fill_square_cropper(img1) | |
| output1 = BytesIO() | |
| squared_img1.save(output1, format="JPEG") | |
| encoded_img1 = base64.b64encode(output1.getvalue()).decode("utf-8") | |
| # Process the second image | |
| response = requests.get(url2) | |
| img2 = Image.open(BytesIO(response.content)).convert("RGB") | |
| squared_img2 = fill_square_cropper(img2) | |
| output2 = BytesIO() | |
| squared_img2.save(output2, format="JPEG") | |
| encoded_img2 = base64.b64encode(output2.getvalue()).decode("utf-8") | |
| return f""" | |
| <html> | |
| <body> | |
| <h2>Square Image Demo</h2> | |
| <p>Image will be squared with color filler where applicable.</p> | |
| <h3>Result 1:</h3> | |
| <img src="data:image/jpeg;base64,{encoded_img1}" /> | |
| <h3>Result 2:</h3> | |
| <img src="data:image/jpeg;base64,{encoded_img2}" /> | |
| <p><a href="/">Back to Home</a></p> | |
| </body> | |
| </html> | |
| """ | |
| # Application Page | |
| def application_page(): | |
| return """ | |
| <html> | |
| <body> | |
| <h2>Square Image Application</h2> | |
| <p>Upload a JPG image to square and fill with color filler.</p> | |
| <form action="/upload/" enctype="multipart/form-data" method="post"> | |
| <input name="file" type="file"> | |
| <input type="submit"> | |
| </form> | |
| <a href="/">Back to Home</a> | |
| </body> | |
| </html> | |
| """ | |
| async def upload_file(file: UploadFile = File(...)): | |
| try: | |
| # Await file upload | |
| contents = await file.read() | |
| img = Image.open(BytesIO(contents)).convert("RGB") | |
| squared_img = fill_square_cropper(img) | |
| # Save the squared image (original size) | |
| output = BytesIO() | |
| squared_img.save(output, format="JPEG") | |
| output.seek(0) | |
| # Encode the full-size image for download | |
| full_size_encoded_img = base64.b64encode(output.getvalue()).decode("utf-8") | |
| # Resize the image for display (512px by 512px) | |
| display_img = squared_img.copy() | |
| display_img.thumbnail((512, 512)) # Resize for display | |
| display_output = BytesIO() | |
| display_img.save(display_output, format="JPEG") | |
| display_output.seek(0) | |
| # Encode the resized display image | |
| display_encoded_img = base64.b64encode(display_output.getvalue()).decode("utf-8") | |
| # Return the HTML response | |
| return HTMLResponse( | |
| content=f""" | |
| <h3>Image successfully squared!</h3> | |
| <img src='data:image/jpeg;base64,{display_encoded_img}' width="512" height="512" /> | |
| <br/> | |
| <a href="data:image/jpeg;base64,{full_size_encoded_img}" download="squared_image.jpg"> | |
| <button>Download Full-Size Image</button> | |
| </a> | |
| """, | |
| media_type="text/html" | |
| ) | |
| except Exception as e: | |
| return HTMLResponse(content=f"<h3>An error occurred: {e}</h3>", media_type="text/html") | |
| if __name__ == "__main__": | |
| import uvicorn | |
| uvicorn.run(app, host="0.0.0.0", port=int(os.environ.get("PORT", 7860))) |