Spaces:
Sleeping
Sleeping
| import gradio as gr | |
| from PIL import Image | |
| import numpy as np | |
| def create_empty_image(): | |
| """ | |
| Create an empty transparent image (512x512, RGBA mode). | |
| :return: Empty PIL.Image object. | |
| """ | |
| return Image.new("RGBA", (512, 512), (0, 0, 0, 0)) | |
| def overlay_images(images, alphas, positions): | |
| """ | |
| Overlay multiple semi-transparent layers and control their positions. | |
| :param images: List of uploaded images (PIL.Image objects). | |
| :param alphas: List of transparency values for each layer (floats between 0 and 1). | |
| :param positions: List of positions for each layer, format: [(x1, y1), (x2, y2), ...]. | |
| :return: Overlayed image with transparent background, overlayed image with black background, and list of individual layer images. | |
| """ | |
| if not images: | |
| return None, None, [] | |
| # Create a transparent canvas (1024x1024) | |
| transparent_canvas = Image.new("RGBA", (1024, 1024), (0, 0, 0, 0)) | |
| # Create a black canvas (1024x1024) | |
| black_canvas = Image.new("RGBA", (1024, 1024), (0, 0, 0, 255)) | |
| layer_images = [] # Store individual layer images | |
| # Overlay each layer | |
| for i, img in enumerate(images): | |
| # Ensure the image is a PIL.Image object | |
| if not isinstance(img, Image.Image): | |
| img = create_empty_image() | |
| # Resize the layer to 512x512 | |
| layer = img.convert("RGBA").resize((512, 512)) | |
| # Set transparency | |
| layer = Image.fromarray( | |
| (np.array(layer) * np.array([1, 1, 1, alphas[i]])).astype(np.uint8) | |
| ) | |
| # Get layer position | |
| x, y = positions[i] | |
| # Expand from bottom-left to top-right | |
| x_offset = x # X coordinate starts from 0 and expands to the right | |
| y_offset = 1024 - y - layer.height # Y coordinate starts from the bottom and expands upward | |
| # Paste the layer onto the transparent canvas | |
| transparent_canvas.paste(layer, (x_offset, y_offset), layer) | |
| # Paste the layer onto the black canvas | |
| black_canvas.paste(layer, (x_offset, y_offset), layer) | |
| # Generate individual layer image | |
| layer_canvas = Image.new("RGBA", (1024, 1024), (0, 0, 0, 0)) | |
| layer_canvas.paste(layer, (x_offset, y_offset), layer) | |
| layer_images.append(layer_canvas) | |
| # If there are fewer than 4 layers, fill with empty images | |
| while len(layer_images) < 4: | |
| layer_images.append(create_empty_image()) | |
| return transparent_canvas, black_canvas, layer_images | |
| def crop_image(image, crop_x_min, crop_x_max, crop_y_min, crop_y_max): | |
| """ | |
| Crop an image. | |
| :param image: Input image (PIL.Image object). | |
| :param crop_x_min: X-axis crop start point. | |
| :param crop_x_max: X-axis crop end point. | |
| :param crop_y_min: Y-axis crop start point. | |
| :param crop_y_max: Y-axis crop end point. | |
| :return: Cropped image (PIL.Image object). | |
| """ | |
| if image is None: | |
| return None | |
| # Ensure the crop range is within the image dimensions | |
| x_min = max(0, min(crop_x_min, image.width)) | |
| x_max = max(0, min(crop_x_max, image.width)) | |
| y_min = max(0, min(crop_y_min, image.height)) | |
| y_max = max(0, min(crop_y_max, image.height)) | |
| # Crop the image | |
| return image.crop((x_min, y_min, x_max, y_max)) | |
| def update_output(image1, image2, image3, image4, alpha1, alpha2, alpha3, alpha4, x1, y1, x2, y2, x3, y3, x4, y4, crop_x_min, crop_x_max, crop_y_min, crop_y_max): | |
| """ | |
| Update the output images. | |
| :param image1, image2, image3, image4: Uploaded images. | |
| :param alpha1, alpha2, alpha3, alpha4: Transparency values for each layer. | |
| :param x1, y1, x2, y2, x3, y3, x4, y4: Positions for each layer. | |
| :param crop_x_min: X-axis crop start point. | |
| :param crop_x_max: X-axis crop end point. | |
| :param crop_y_min: Y-axis crop start point. | |
| :param crop_y_max: Y-axis crop end point. | |
| :return: Cropped transparent background image, black background image, and individual layer images. | |
| """ | |
| # Print logs to check the type and content of each input | |
| print("image1:", type(image1), image1) | |
| print("image2:", type(image2), image2) | |
| print("image3:", type(image3), image3) | |
| print("image4:", type(image4), image4) | |
| print("alpha1:", type(alpha1), alpha1) | |
| print("alpha2:", type(alpha2), alpha2) | |
| print("alpha3:", type(alpha3), alpha3) | |
| print("alpha4:", type(alpha4), alpha4) | |
| print("x1:", type(x1), x1) | |
| print("y1:", type(y1), y1) | |
| print("x2:", type(x2), x2) | |
| print("y2:", type(y2), y2) | |
| print("x3:", type(x3), x3) | |
| print("y3:", type(y3), y3) | |
| print("x4:", type(x4), x4) | |
| print("y4:", type(y4), y4) | |
| print("crop_x_min:", type(crop_x_min), crop_x_min) | |
| print("crop_x_max:", type(crop_x_max), crop_x_max) | |
| print("crop_y_min:", type(crop_y_min), crop_y_min) | |
| print("crop_y_max:", type(crop_y_max), crop_y_max) | |
| # If an image is None, use an empty image | |
| images = [ | |
| image1 if image1 is not None else create_empty_image(), | |
| image2 if image2 is not None else create_empty_image(), | |
| image3 if image3 is not None else create_empty_image(), | |
| image4 if image4 is not None else create_empty_image() | |
| ] | |
| alphas = [alpha1, alpha2, alpha3, alpha4] # Transparency list | |
| positions = [(x1, y1), (x2, y2), (x3, y3), (x4, y4)] # Position list | |
| # Call the overlay function | |
| transparent_image, black_image, layer_images = overlay_images(images, alphas, positions) | |
| # Crop the output images | |
| transparent_image = crop_image(transparent_image, crop_x_min, crop_x_max, crop_y_min, crop_y_max) | |
| black_image = crop_image(black_image, crop_x_min, crop_x_max, crop_y_min, crop_y_max) | |
| layer_images = [crop_image(img, crop_x_min, crop_x_max, crop_y_min, crop_y_max) for img in layer_images] | |
| # Return 6 values (cropped transparent background image + black background image + 4 individual layer images) | |
| return [transparent_image, black_image] + layer_images | |
| # Example data | |
| example_images = [ | |
| Image.open("芙宁娜_yellow.webp") if "芙宁娜_yellow.webp" else create_empty_image(), | |
| Image.open("妮露_blue.webp") if "妮露_blue.webp" else create_empty_image(), | |
| create_empty_image(), # Layer 3 is an empty image | |
| create_empty_image() # Layer 4 is an empty image | |
| ] | |
| example_alphas = [1.0, 1.0, 1.0, 1.0] # Example transparency values | |
| example_positions = [(101, 0), (264, 0), (0, 0), (0, 0)] # Example positions | |
| example_crop_x = (160, 850) # Example X-axis crop range | |
| example_crop_y = (360, 1020) # Example Y-axis crop range | |
| # Gradio interface | |
| with gr.Blocks() as demo: | |
| gr.Markdown("## 🎨 Layer Overlay Application") | |
| gr.Markdown("Upload multiple semi-transparent layers (PNG format), set transparency and position, and generate the overlayed image.") | |
| with gr.Row(): | |
| # Left column: Inputs | |
| with gr.Column(): | |
| gr.Markdown("### Upload Layers") | |
| image1 = gr.Image(label="Layer 1", type="pil", image_mode="RGBA") | |
| image2 = gr.Image(label="Layer 2", type="pil", image_mode="RGBA") | |
| image3 = gr.Image(label="Layer 3", type="pil", image_mode="RGBA") | |
| image4 = gr.Image(label="Layer 4", type="pil", image_mode="RGBA") | |
| gr.Markdown("### Set Transparency") | |
| alpha1 = gr.Slider(0, 1, value=1, label="Layer 1 Transparency") | |
| alpha2 = gr.Slider(0, 1, value=1, label="Layer 2 Transparency") | |
| alpha3 = gr.Slider(0, 1, value=1, label="Layer 3 Transparency") | |
| alpha4 = gr.Slider(0, 1, value=1, label="Layer 4 Transparency") | |
| gr.Markdown("### Set Positions") | |
| with gr.Row(): | |
| x1 = gr.Slider(0, 512, value=0, label="Layer 1 X Position") | |
| y1 = gr.Slider(0, 512, value=0, label="Layer 1 Y Position") | |
| with gr.Row(): | |
| x2 = gr.Slider(0, 512, value=0, label="Layer 2 X Position") | |
| y2 = gr.Slider(0, 512, value=0, label="Layer 2 Y Position") | |
| with gr.Row(): | |
| x3 = gr.Slider(0, 512, value=0, label="Layer 3 X Position") | |
| y3 = gr.Slider(0, 512, value=0, label="Layer 3 Y Position") | |
| with gr.Row(): | |
| x4 = gr.Slider(0, 512, value=0, label="Layer 4 X Position") | |
| y4 = gr.Slider(0, 512, value=0, label="Layer 4 Y Position") | |
| gr.Markdown("### Set Crop Range") | |
| with gr.Row(): | |
| crop_x_min = gr.Slider(0, 1024, value=0, label="X-axis Crop Start") | |
| crop_x_max = gr.Slider(0, 1024, value=1024, label="X-axis Crop End") | |
| with gr.Row(): | |
| crop_y_min = gr.Slider(0, 1024, value=0, label="Y-axis Crop Start") | |
| crop_y_max = gr.Slider(0, 1024, value=1024, label="Y-axis Crop End") | |
| run_button = gr.Button("Generate Overlayed Image") | |
| # Right column: Outputs | |
| with gr.Column(): | |
| gr.Markdown("### Overlay Results") | |
| transparent_output = gr.Image(label="Overlayed Image (Transparent Background)", type="pil") | |
| black_output = gr.Image(label="Overlayed Image (Black Background)", type="pil") | |
| gr.Markdown("### Individual Layer Images") | |
| layer1_image = gr.Image(label="Layer 1 Image", type="pil") | |
| layer2_image = gr.Image(label="Layer 2 Image", type="pil") | |
| layer3_image = gr.Image(label="Layer 3 Image", type="pil") | |
| layer4_image = gr.Image(label="Layer 4 Image", type="pil") | |
| # Bind events | |
| run_button.click( | |
| update_output, | |
| inputs=[ | |
| image1, image2, image3, image4, # Images | |
| alpha1, alpha2, alpha3, alpha4, # Transparency | |
| x1, y1, x2, y2, x3, y3, x4, y4, # Positions | |
| crop_x_min, crop_x_max, # X-axis crop range | |
| crop_y_min, crop_y_max # Y-axis crop range | |
| ], | |
| outputs=[transparent_output, black_output, layer1_image, layer2_image, layer3_image, layer4_image] | |
| ) | |
| # Add examples | |
| gr.Examples( | |
| examples=[ | |
| [ | |
| example_images[0], example_images[1], example_images[2], example_images[3], # Images | |
| example_alphas[0], example_alphas[1], example_alphas[2], example_alphas[3], # Transparency | |
| example_positions[0][0], example_positions[0][1], # Layer 1 position | |
| example_positions[1][0], example_positions[1][1], # Layer 2 position | |
| example_positions[2][0], example_positions[2][1], # Layer 3 position | |
| example_positions[3][0], example_positions[3][1], # Layer 4 position | |
| example_crop_x[0], example_crop_x[1], # X-axis crop range | |
| example_crop_y[0], example_crop_y[1] # Y-axis crop range | |
| ] | |
| ], | |
| inputs=[ | |
| image1, image2, image3, image4, # Images | |
| alpha1, alpha2, alpha3, alpha4, # Transparency | |
| x1, y1, x2, y2, x3, y3, x4, y4, # Positions | |
| crop_x_min, crop_x_max, # X-axis crop range | |
| crop_y_min, crop_y_max # Y-axis crop range | |
| ], | |
| outputs=[transparent_output, black_output, layer1_image, layer2_image, layer3_image, layer4_image], | |
| fn=update_output, | |
| cache_examples=True | |
| ) | |
| # Launch the application | |
| if __name__ == "__main__": | |
| demo.launch(share=True) |