Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -8,7 +8,6 @@ def process_transparent_image(image, padding_color):
|
|
8 |
"""Handle images with transparency by converting transparent areas to a solid color."""
|
9 |
if image.mode in ("RGBA", "LA") or (image.mode == "P" and "transparency" in image.info):
|
10 |
alpha = image.convert("RGBA").getchannel("A") # Extract the alpha channel
|
11 |
-
# Create a new image with the background color
|
12 |
background = Image.new("RGBA", image.size, padding_color + (255,))
|
13 |
background.paste(image, mask=alpha) # Paste with transparency mask
|
14 |
return background.convert("RGB") # Convert back to RGB
|
@@ -16,28 +15,21 @@ def process_transparent_image(image, padding_color):
|
|
16 |
|
17 |
def resize_and_pad(image, target_size):
|
18 |
"""Resize the image and pad it to match target size."""
|
19 |
-
# Randomly select black or white as the background color
|
20 |
padding_color = (255, 255, 255) if random.choice([True, False]) else (0, 0, 0)
|
21 |
-
|
22 |
-
# Handle transparent images
|
23 |
img = process_transparent_image(image, padding_color)
|
24 |
|
25 |
aspect_ratio = img.width / img.height
|
26 |
target_aspect_ratio = target_size[0] / target_size[1]
|
27 |
|
28 |
if aspect_ratio > target_aspect_ratio:
|
29 |
-
# Wider than target aspect ratio
|
30 |
new_width = target_size[0]
|
31 |
new_height = int(new_width / aspect_ratio)
|
32 |
else:
|
33 |
-
# Taller than target aspect ratio
|
34 |
new_height = target_size[1]
|
35 |
new_width = int(new_height * aspect_ratio)
|
36 |
|
37 |
-
# Use high-quality resampling for resizing
|
38 |
img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
|
39 |
|
40 |
-
# Create a new image with the determined background color
|
41 |
new_img = Image.new("RGB", target_size, padding_color)
|
42 |
offset = ((target_size[0] - new_width) // 2, (target_size[1] - new_height) // 2)
|
43 |
new_img.paste(img, offset)
|
@@ -48,23 +40,18 @@ def combine_images(images, target_size=(2048, 2048)):
|
|
48 |
num_images = len(images)
|
49 |
output_images = []
|
50 |
|
51 |
-
# Group images into chunks of 4
|
52 |
for i in range(0, num_images, 4):
|
53 |
group = images[i:i+4]
|
54 |
if len(group) < 4:
|
55 |
continue
|
56 |
|
57 |
-
# Resize and pad each image
|
58 |
resized_images = [resize_and_pad(img, (512, 512)) for img in group]
|
59 |
-
|
60 |
-
# Create a blank canvas
|
61 |
combined_img = Image.new("RGB", (1024, 1024), (0, 0, 0))
|
62 |
combined_img.paste(resized_images[0], (0, 0))
|
63 |
combined_img.paste(resized_images[1], (512, 0))
|
64 |
combined_img.paste(resized_images[2], (0, 512))
|
65 |
combined_img.paste(resized_images[3], (512, 512))
|
66 |
|
67 |
-
# Resize if the final size exceeds target
|
68 |
if combined_img.width > target_size[0] or combined_img.height > target_size[1]:
|
69 |
combined_img = combined_img.resize(target_size, Image.Resampling.LANCZOS)
|
70 |
|
@@ -76,7 +63,6 @@ def process_images(uploaded_images):
|
|
76 |
"""Main processing function."""
|
77 |
images = [Image.open(img) for img in uploaded_images]
|
78 |
combined_images = combine_images(images)
|
79 |
-
result_paths = []
|
80 |
|
81 |
# Save combined images
|
82 |
output_dir = "output_images"
|
@@ -84,21 +70,37 @@ def process_images(uploaded_images):
|
|
84 |
for idx, img in enumerate(combined_images):
|
85 |
output_path = os.path.join(output_dir, f"combined_{idx + 1}.png")
|
86 |
img.save(output_path)
|
87 |
-
result_paths.append(output_path)
|
88 |
|
89 |
-
# Create a ZIP file
|
90 |
zip_path = "combined_images.zip"
|
91 |
shutil.make_archive("combined_images", 'zip', output_dir)
|
92 |
-
|
93 |
-
return zip_path
|
94 |
|
95 |
# Gradio UI
|
96 |
-
|
97 |
-
|
98 |
-
|
99 |
-
|
100 |
-
|
101 |
-
|
102 |
-
)
|
103 |
-
|
104 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
8 |
"""Handle images with transparency by converting transparent areas to a solid color."""
|
9 |
if image.mode in ("RGBA", "LA") or (image.mode == "P" and "transparency" in image.info):
|
10 |
alpha = image.convert("RGBA").getchannel("A") # Extract the alpha channel
|
|
|
11 |
background = Image.new("RGBA", image.size, padding_color + (255,))
|
12 |
background.paste(image, mask=alpha) # Paste with transparency mask
|
13 |
return background.convert("RGB") # Convert back to RGB
|
|
|
15 |
|
16 |
def resize_and_pad(image, target_size):
|
17 |
"""Resize the image and pad it to match target size."""
|
|
|
18 |
padding_color = (255, 255, 255) if random.choice([True, False]) else (0, 0, 0)
|
|
|
|
|
19 |
img = process_transparent_image(image, padding_color)
|
20 |
|
21 |
aspect_ratio = img.width / img.height
|
22 |
target_aspect_ratio = target_size[0] / target_size[1]
|
23 |
|
24 |
if aspect_ratio > target_aspect_ratio:
|
|
|
25 |
new_width = target_size[0]
|
26 |
new_height = int(new_width / aspect_ratio)
|
27 |
else:
|
|
|
28 |
new_height = target_size[1]
|
29 |
new_width = int(new_height * aspect_ratio)
|
30 |
|
|
|
31 |
img = img.resize((new_width, new_height), Image.Resampling.LANCZOS)
|
32 |
|
|
|
33 |
new_img = Image.new("RGB", target_size, padding_color)
|
34 |
offset = ((target_size[0] - new_width) // 2, (target_size[1] - new_height) // 2)
|
35 |
new_img.paste(img, offset)
|
|
|
40 |
num_images = len(images)
|
41 |
output_images = []
|
42 |
|
|
|
43 |
for i in range(0, num_images, 4):
|
44 |
group = images[i:i+4]
|
45 |
if len(group) < 4:
|
46 |
continue
|
47 |
|
|
|
48 |
resized_images = [resize_and_pad(img, (512, 512)) for img in group]
|
|
|
|
|
49 |
combined_img = Image.new("RGB", (1024, 1024), (0, 0, 0))
|
50 |
combined_img.paste(resized_images[0], (0, 0))
|
51 |
combined_img.paste(resized_images[1], (512, 0))
|
52 |
combined_img.paste(resized_images[2], (0, 512))
|
53 |
combined_img.paste(resized_images[3], (512, 512))
|
54 |
|
|
|
55 |
if combined_img.width > target_size[0] or combined_img.height > target_size[1]:
|
56 |
combined_img = combined_img.resize(target_size, Image.Resampling.LANCZOS)
|
57 |
|
|
|
63 |
"""Main processing function."""
|
64 |
images = [Image.open(img) for img in uploaded_images]
|
65 |
combined_images = combine_images(images)
|
|
|
66 |
|
67 |
# Save combined images
|
68 |
output_dir = "output_images"
|
|
|
70 |
for idx, img in enumerate(combined_images):
|
71 |
output_path = os.path.join(output_dir, f"combined_{idx + 1}.png")
|
72 |
img.save(output_path)
|
|
|
73 |
|
|
|
74 |
zip_path = "combined_images.zip"
|
75 |
shutil.make_archive("combined_images", 'zip', output_dir)
|
76 |
+
return combined_images, zip_path
|
|
|
77 |
|
78 |
# Gradio UI
|
79 |
+
def main_interface():
|
80 |
+
with gr.Blocks() as interface:
|
81 |
+
with gr.Row():
|
82 |
+
gr.Markdown("### Image Resizer and Combiner")
|
83 |
+
|
84 |
+
with gr.Row():
|
85 |
+
with gr.Column(scale=1):
|
86 |
+
uploaded_files = gr.Files(
|
87 |
+
file_types=["image"], label="Upload Images", interactive=True, elem_id="upload-box"
|
88 |
+
)
|
89 |
+
with gr.Column(scale=2):
|
90 |
+
preview_gallery = gr.Gallery(label="Preview Combined Images").style(grid=4)
|
91 |
+
|
92 |
+
convert_button = gr.Button("Convert and Combine", elem_id="convert-button")
|
93 |
+
download_zip = gr.Button("Download ZIP", elem_id="download-zip", visible=False)
|
94 |
+
|
95 |
+
output_zip = gr.File(label="Download Combined ZIP", visible=False)
|
96 |
+
|
97 |
+
# Bind functions
|
98 |
+
convert_button.click(
|
99 |
+
process_images,
|
100 |
+
inputs=[uploaded_files],
|
101 |
+
outputs=[preview_gallery, output_zip],
|
102 |
+
)
|
103 |
+
download_zip.click(lambda zip_file: zip_file, inputs=[output_zip], outputs=output_zip)
|
104 |
+
return interface
|
105 |
+
|
106 |
+
main_interface().launch()
|