Spaces:
Runtime error
Runtime error
import gradio as gr | |
from PIL import Image, ImageStat | |
import numpy as np | |
import os | |
import shutil | |
import random | |
def get_dominant_color(image): | |
"""Get the dominant color of an image or return None.""" | |
try: | |
stat = ImageStat.Stat(image) | |
r, g, b = stat.mean[:3] | |
return int(r), int(g), int(b) | |
except: | |
return None | |
def resize_and_pad(image, target_size): | |
"""Resize the image and pad it to match target size.""" | |
img = image.convert("RGB") | |
aspect_ratio = img.width / img.height | |
target_aspect_ratio = target_size[0] / target_size[1] | |
if aspect_ratio > target_aspect_ratio: | |
# Wider than target aspect ratio | |
new_width = target_size[0] | |
new_height = int(new_width / aspect_ratio) | |
else: | |
# Taller than target aspect ratio | |
new_height = target_size[1] | |
new_width = int(new_height * aspect_ratio) | |
# Use Image.Resampling.LANCZOS instead of Image.ANTIALIAS | |
img = img.resize((new_width, new_height), Image.Resampling.LANCZOS) | |
# Determine padding color | |
dominant_color = get_dominant_color(img) | |
if dominant_color is None: | |
dominant_color = (255, 255, 255) if random.choice([True, False]) else (0, 0, 0) | |
# Create a new image with the determined background color | |
new_img = Image.new("RGB", target_size, dominant_color) | |
offset = ((target_size[0] - new_width) // 2, (target_size[1] - new_height) // 2) | |
new_img.paste(img, offset) | |
return new_img | |
def combine_images(images, target_size=(2048, 2048)): | |
"""Combine four images into a single one.""" | |
num_images = len(images) | |
output_images = [] | |
# Group images into chunks of 4 | |
for i in range(0, num_images, 4): | |
group = images[i:i+4] | |
if len(group) < 4: | |
continue | |
# Resize and pad each image | |
resized_images = [resize_and_pad(img, (512, 512)) for img in group] | |
# Create a blank canvas | |
combined_img = Image.new("RGB", (1024, 1024), (0, 0, 0)) | |
combined_img.paste(resized_images[0], (0, 0)) | |
combined_img.paste(resized_images[1], (512, 0)) | |
combined_img.paste(resized_images[2], (0, 512)) | |
combined_img.paste(resized_images[3], (512, 512)) | |
# Resize if the final size exceeds target | |
if combined_img.width > target_size[0] or combined_img.height > target_size[1]: | |
combined_img = combined_img.resize(target_size, Image.Resampling.LANCZOS) | |
output_images.append(combined_img) | |
return output_images | |
def process_images(uploaded_images): | |
"""Main processing function.""" | |
images = [Image.open(img) for img in uploaded_images] | |
combined_images = combine_images(images) | |
result_paths = [] | |
# Save combined images | |
output_dir = "output_images" | |
os.makedirs(output_dir, exist_ok=True) | |
for idx, img in enumerate(combined_images): | |
output_path = os.path.join(output_dir, f"combined_{idx + 1}.png") | |
img.save(output_path) | |
result_paths.append(output_path) | |
# Create a ZIP file | |
zip_path = "combined_images.zip" | |
shutil.make_archive("combined_images", 'zip', output_dir) | |
return zip_path | |
# Gradio UI | |
interface = gr.Interface( | |
fn=process_images, | |
inputs=gr.Files(file_types=["image"], label="Upload Images"), | |
outputs=gr.File(label="Download ZIP"), | |
title="Image Resizer and Combiner", | |
description="Upload multiple images. This tool will resize and pad them to match a consistent size, then combine every four images into one. The output will be resized if it exceeds 2048x2048, and all results are available as a ZIP file." | |
) | |
interface.launch() |