Spaces:
Runtime error
Runtime error
import gradio as gr | |
from PIL import Image, ImageDraw, ImageFont, ImageSequence | |
import numpy as np | |
def create_grid(image_file, grid_x, grid_y, font_size, font_color, position, border_size, border_color): | |
image_file.file.seek(0) # Seek to the beginning of the file | |
# Open the image from bytes | |
img = Image.open(image_file.name) | |
total_frames = img.n_frames | |
selected_frames_count = grid_x * grid_y | |
# Select evenly spaced frames | |
selected_frames_indices = np.linspace(0, total_frames - 1, selected_frames_count).astype(int) | |
selected_frames = [img.seek(i) or img.copy() for i in selected_frames_indices] | |
# Modify frames by adding border and number | |
modified_frames = [] | |
try: | |
font = ImageFont.truetype("Lato-Regular.ttf", font_size) | |
except IOError: | |
print("Font not found, using default font.") | |
font = ImageFont.load_default() | |
positions = { | |
"Top Left": (20, 20), | |
"Top Right": (img.width - 20 - font_size, 20), | |
"Bottom Left": (20, img.height - 20 - font_size), | |
"Bottom Right": (img.width - 20 - font_size, img.height - 20 - font_size) | |
} | |
for i, frame in enumerate(selected_frames): | |
# Add border | |
border_width = border_size | |
frame_with_border = Image.new('RGB', (frame.width + 2*border_width, frame.height + 2*border_width), border_color.lower()) | |
frame_with_border.paste(frame, (border_width, border_width)) | |
# Add number | |
draw = ImageDraw.Draw(frame_with_border) | |
text = str(i + 1) | |
text_position = (border_width + positions[position][0], border_width + positions[position][1]) | |
draw.text(text_position, text, font=font, fill=font_color) | |
modified_frames.append(frame_with_border) | |
# Combine modified frames into a grid | |
grid_width = modified_frames[0].width * grid_x | |
grid_height = modified_frames[0].height * grid_y | |
grid_img = Image.new('RGB', (grid_width, grid_height), border_color.lower()) | |
for i, frame in enumerate(modified_frames): | |
x_offset = (i % grid_x) * frame.width | |
y_offset = (i // grid_x) * frame.height | |
grid_img.paste(frame, (x_offset, y_offset)) | |
output_info = f"Grid size: {grid_x} x {grid_y}\n\nSelected Frames: {selected_frames_count} / {total_frames} ({selected_frames_count / total_frames * 100:.2f}%)" | |
return grid_img, output_info | |
def gif_info(image_file, grid_x, grid_y, font_size, font_color, position, border_size, border_color): | |
image_file.file.seek(0) | |
img = Image.open(image_file.name) | |
total_frames = img.n_frames | |
frame_rate = img.info.get('duration', 100) / 1000.0 # Convert to seconds | |
# Generate grid using create_grid function | |
grid_img, output_info = create_grid(image_file, grid_x, grid_y, font_size, font_color, position, border_size, border_color) | |
gif_details = f"\n\n**Total Frames:** {total_frames}\n\n**Frame Rate:** {frame_rate} sec/frame\n\n{output_info}" | |
return grid_img, gif_details | |
with gr.Blocks() as app: | |
gr.Markdown('## GIF Grid Generator') | |
gr.Markdown('Upload a GIF to generate a grid from its frames. Use the sliders to adjust the grid size and text settings.') | |
with gr.Row(): | |
with gr.Column(): | |
control_image = gr.File(label="Upload a GIF", type="file", elem_id="file_upload", file_types=[".gif"]) | |
gif_details = gr.Markdown("Upload a gif") | |
grid_x_slider = gr.Slider(minimum=1, maximum=10, step=1, value=3, label="Grid X Size") | |
grid_y_slider = gr.Slider(minimum=1, maximum=10, step=1, value=3, label="Grid Y Size") | |
font_color_dropdown = gr.Dropdown(choices=["Black", "White", "Red", "Green", "Blue"], value="White", label="Numbering Color") | |
position_radio = gr.Radio(choices=["Top Left", "Top Right", "Bottom Left", "Bottom Right"], value="Top Left", label="Numbering Position") | |
font_size_slider = gr.Slider(minimum=10, maximum=100, step=5, value=40, label="Font Size") | |
border_color_dropdown = gr.Dropdown(choices=["Black", "White", "Red", "Green", "Blue"], value="White", label="Border Color") | |
border_size_slider = gr.Slider(minimum=0, maximum=100, step=5, value=10, label="Border Size") | |
with gr.Column(): | |
result_image = gr.Image(label="Generated Grid") | |
# Use .change() method to listen for changes in any of the controls | |
control_image.change(gif_info, inputs=[control_image, grid_x_slider, grid_y_slider, font_size_slider, font_color_dropdown, position_radio, border_size_slider, border_color_dropdown], outputs=[result_image, gif_details]) | |
grid_x_slider.change(gif_info, inputs=[control_image, grid_x_slider, grid_y_slider, font_size_slider, font_color_dropdown, position_radio, border_size_slider, border_color_dropdown], outputs=[result_image, gif_details]) | |
grid_y_slider.change(gif_info, inputs=[control_image, grid_x_slider, grid_y_slider, font_size_slider, font_color_dropdown, position_radio, border_size_slider, border_color_dropdown], outputs=[result_image, gif_details]) | |
font_size_slider.change(gif_info, inputs=[control_image, grid_x_slider, grid_y_slider, font_size_slider, font_color_dropdown, position_radio, border_size_slider, border_color_dropdown], outputs=[result_image, gif_details]) | |
font_color_dropdown.change(gif_info, inputs=[control_image, grid_x_slider, grid_y_slider, font_size_slider, font_color_dropdown, position_radio, border_size_slider, border_color_dropdown], outputs=[result_image, gif_details]) | |
position_radio.change(gif_info, inputs=[control_image, grid_x_slider, grid_y_slider, font_size_slider, font_color_dropdown, position_radio, border_size_slider, border_color_dropdown], outputs=[result_image, gif_details]) | |
border_size_slider.change(gif_info, inputs=[control_image, grid_x_slider, grid_y_slider, font_size_slider, font_color_dropdown, position_radio, border_size_slider, border_color_dropdown], outputs=[result_image, gif_details]) | |
border_color_dropdown.change(gif_info, inputs=[control_image, grid_x_slider, grid_y_slider, font_size_slider, font_color_dropdown, position_radio, border_size_slider, border_color_dropdown], outputs=[result_image, gif_details]) | |
if __name__ == "__main__": | |
app.launch() | |