import gradio as gr from PIL import Image def composite_images(bg_image, overlay_image, x, y, scale, transparency, flip, grayscale): if bg_image is None or overlay_image is None: return None bg = bg_image.convert("RGBA") overlay = overlay_image.convert("RGBA") # Apply optional effects if flip: overlay = overlay.transpose(Image.FLIP_LEFT_RIGHT) if grayscale: overlay = overlay.convert("L").convert("RGBA") # Resize overlay new_size = (int(overlay.width * scale), int(overlay.height * scale)) overlay = overlay.resize(new_size, resample=Image.LANCZOS) # ✅ FIXED here # Adjust transparency alpha = int(255 * transparency) r, g, b, a = overlay.split() a = a.point(lambda p: alpha) overlay = Image.merge("RGBA", (r, g, b, a)) # Create composite image composed = bg.copy() composed.paste(overlay, (int(x), int(y)), overlay) return composed with gr.Blocks() as demo: gr.Markdown("### 🖼️ Overlay Image Composer with Transparency & Effects") with gr.Row(): bg_input = gr.Image(label="Background Image", type="pil") overlay_input = gr.Image(label="Overlay Image", type="pil") with gr.Row(): x = gr.Slider(0, 1024, value=100, step=1, label="X Position") y = gr.Slider(0, 1024, value=100, step=1, label="Y Position") with gr.Row(): scale = gr.Slider(0.1, 3.0, value=1.0, step=0.1, label="Overlay Scale") transparency = gr.Slider(0, 1, value=1.0, step=0.01, label="Overlay Transparency") with gr.Row(): flip = gr.Checkbox(label="Flip Overlay Horizontally") grayscale = gr.Checkbox(label="Convert Overlay to Grayscale") output_image = gr.Image(label="Composed Image", type="pil") run_btn = gr.Button("Generate Composite") download_btn = gr.Button("Download") run_btn.click( composite_images, inputs=[bg_input, overlay_input, x, y, scale, transparency, flip, grayscale], outputs=output_image ) def download_image(img): if img is not None: img.save("composed_output.png") return "composed_output.png" return None download_btn.click(download_image, inputs=output_image, outputs=gr.File(label="Download Link")) demo.launch()