Skip to content

Instantly share code, notes, and snippets.

@deadjakk
Created January 20, 2025 03:58
Show Gist options
  • Save deadjakk/6eb5cfde7319f0cb068b341270fdf553 to your computer and use it in GitHub Desktop.
Save deadjakk/6eb5cfde7319f0cb068b341270fdf553 to your computer and use it in GitHub Desktop.
gif-2-spritesheet
#!/usr/bin/env python
# forked from https://github.com/JingShing/GIF-To-SpriteSheet
from argparse import ArgumentParser
from pathlib import Path
from PIL import Image, ImageSequence
import os, sys
def select_folder(title):
folder = filedialog.askdirectory(title=title)
return folder
def convert_gif_to_spritesheet(gif_path, output_folder, columns="auto"):
if os.path.exists(gif_path) is False:
print(f"error: {gif_path} does not exist")
exit(1)
if gif_path.lower().endswith('.gif') is False:
print(f"error: {gif_path} is not a gif")
exit(1)
with Image.open(gif_path) as gif:
frames = [frame.copy() for frame in ImageSequence.Iterator(gif)]
if frames:
if columns == "auto":
columns = len(frames)
else:
columns = int(columns)
frame_width, frame_height = frames[0].size
rows = (len(frames) + columns - 1) // columns
sheet_width = columns * frame_width
sheet_height = rows * frame_height
spritesheet = Image.new('RGBA', (sheet_width, sheet_height))
for i, frame in enumerate(frames):
x = (i % columns) * frame_width
y = (i // columns) * frame_height
spritesheet.paste(frame, (x, y))
if not output_folder:
output_folder = os.path.dirname(gif_path)
dirname = os.path.dirname(gif_path)
basename = os.path.basename(gif_path).replace(".gif",".png")
output_path = os.path.join(dirname, basename)
print(f"output path:{output_folder}")
spritesheet.save(output_path)
print(f"Saved: {output_path}")
def convert_gif_to_spritesheet_dir(source_folder, output_folder=None, columns="auto"):
for filename in os.listdir(source_folder):
if filename.lower().endswith('.gif') is False:
print(f"{filename} is not a gif, skipping...")
continue
gif_path = os.path.join(source_folder, filename)
convert_gif_to_spritesheet(gif_path, output_folder, columns)
# GUI Setup
def main():
try:
from tkinter import filedialog
import tkinter as tk
except:
print("tkinter library is not installed, unfortunately the GUI cannot load. try passing the -i arg to bypass the GUI", file=sys.stderr)
exit(1)
root = tk.Tk()
root.title("GIF to SpriteSheet Converter")
root.geometry("500x300")
source_folder = None
output_folder = None
def select_source_folder():
nonlocal source_folder
source_folder = select_folder("Select Source Folder")
if source_folder:
lbl_source.config(text=f"Source Folder: {source_folder}")
def select_output_folder():
nonlocal output_folder
output_folder = select_folder("Select Output Folder")
if output_folder:
lbl_output.config(text=f"Output Folder: {output_folder}")
def process_conversion():
columns = entry_columns.get()
if not columns:
columns = "auto"
if not columns.isdigit() or int(columns) < 1 or columns != "auto":
print("Please enter a valid number of columns or 'auto' to use the number of present frames instead.")
return
columns = int(columns) if columns != "auto" else "auto"
if not source_folder:
print("Please make sure all inputs are set.")
return
convert_gif_to_spritesheet_dir(source_folder, output_folder, columns)
print("Conversion completed!")
tk.Button(root, text="Select Source Folder", command=select_source_folder).pack(pady=5)
lbl_source = tk.Label(root, text="Source Folder: Not selected")
lbl_source.pack()
tk.Button(root, text="Select Output Folder", command=select_output_folder).pack(pady=5)
lbl_output = tk.Label(root, text="Output Folder: Not selected")
lbl_output.pack()
tk.Label(root, text="Enter number of columns (or auto to use number of GIF frames found):").pack(pady=5)
entry_columns = tk.Entry(root)
entry_columns.pack()
btn_convert = tk.Button(root, text="Start Conversion", command=process_conversion)
btn_convert.pack(pady=20)
root.mainloop()
if __name__ == "__main__":
parser = ArgumentParser()
parser.add_argument("-i", help="input GIF or directory containing GIFs to process, if this is not specified, the GUI will run")
parser.add_argument("-c", help="number of columns for the spritesheet, enter 'auto' to use the number of frames present in the GIF(s) (optional, you probably don't need this)", default="auto")
args = parser.parse_args()
if args.i:
if os.path.isdir(args.i):
convert_gif_to_spritesheet_dir(args.i, args.i, columns=args.c)
else:
output_folder = str(Path(args.i).resolve())
convert_gif_to_spritesheet(args.i, output_folder, columns=args.c)
else:
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment