Spaces:
Running
Running
import gradio as gr | |
from PIL import Image | |
import io | |
import numpy as np | |
from math import cos, radians, sin | |
def create_gif(editor1_output, editor2_output, transition_type): | |
img1 = editor1_output["composite"].convert('RGBA') | |
img2 = editor2_output["composite"].convert('RGBA') | |
frames = [] | |
duration = 100 # Duration for each frame in milliseconds | |
total_frames = 18 # Total number of frames | |
size = (256, 256) # Fixed size for both images | |
img1 = img1.resize(size, Image.LANCZOS) | |
img2 = img2.resize(size, Image.LANCZOS) | |
if transition_type == "slide": | |
full_width = size[0] | |
step = full_width // (total_frames // 2) | |
# Create sliding transition | |
for i in range(0, full_width, step): | |
frame = Image.new('RGBA', size) | |
frame.paste(img1, (0, 0)) | |
frame.paste(img2.crop((0, 0, i, size[1])), (full_width - i, 0), mask=img2.crop((0, 0, i, size[1]))) | |
frames.append(frame.convert('P', palette=Image.ADAPTIVE)) | |
for i in range(full_width, 0, -step): | |
frame = Image.new('RGBA', size) | |
frame.paste(img2, (0, 0)) | |
frame.paste(img1.crop((0, 0, i, size[1])), (full_width - i, 0), mask=img1.crop((0, 0, i, size[1]))) | |
frames.append(frame.convert('P', palette=Image.ADAPTIVE)) | |
else: # rotate transition | |
for angle in range(0, 360, 360 // total_frames): | |
mask = Image.new('L', size, 0) | |
draw = Image.Draw(mask) | |
draw.pieslice([0, 0, size[0], size[1]], -90, angle - 90, fill=255) | |
frame = Image.composite(img2, img1, mask) | |
frames.append(frame.convert('P', palette=Image.ADAPTIVE)) | |
# Save as GIF | |
output = io.BytesIO() | |
frames[0].save(output, format='GIF', save_all=True, append_images=frames[1:], duration=duration, loop=0, optimize=True) | |
output.seek(0) | |
# Save the GIF to a temporary file | |
temp_output_path = "output.gif" | |
with open(temp_output_path, "wb") as f: | |
f.write(output.getvalue()) | |
return temp_output_path | |
# Gradio interface | |
with gr.Blocks() as iface: | |
gr.Markdown("# 2GIF Transition Slider") | |
with gr.Row(): | |
with gr.Column(scale=2): | |
image_editor1 = gr.ImageEditor( | |
label="Edit Image 1", | |
brush=gr.Brush(colors=["#ff0000", "#00ff00", "#0000ff"]), | |
eraser=gr.Eraser(default_size=10), | |
height=400, | |
width="100%", | |
crop_size="1:1", | |
layers=True, | |
type="pil" | |
) | |
with gr.Column(scale=2): | |
image_editor2 = gr.ImageEditor( | |
label="Edit Image 2", | |
brush=gr.Brush(colors=["#ff0000", "#00ff00", "#0000ff"]), | |
eraser=gr.Eraser(default_size=10), | |
height=400, | |
width="100%", | |
crop_size="1:1", | |
layers=True, | |
type="pil" | |
) | |
with gr.Row(): | |
transition_type = gr.Radio(["slide", "rotate"], label="Transition Type", value="slide") | |
generate_button = gr.Button("Generate GIF") | |
with gr.Row(): | |
output_gif = gr.Image(type="filepath", label="Generated GIF", height=300) | |
generate_button.click( | |
create_gif, | |
inputs=[image_editor1, image_editor2, transition_type], | |
outputs=[output_gif] | |
) | |
# Launch the interface | |
iface.launch() |