Project
Function
Sample CLI
gway screen animate-gif
References
['abort', 'resource']
Full Code
def animate_gif(pattern, *, output_gif=None):
resolved = gw.resource(pattern)
if os.path.isdir(resolved):
pngs = sorted(glob.glob(os.path.join(resolved, "*.png")))
if not pngs:
gw.abort(f"No .png files found in directory: {resolved}")
sample_file = os.path.basename(pngs[0])
base_dir = resolved
else:
sample_file = os.path.basename(resolved)
base_dir = os.path.dirname(resolved) or "."
# Detect [n] or ā - nā patterns (falls back to ctime sort)
bracket = re.search(r'\[(\d+)\]', sample_file)
dash = re.search(r'^(.*?)([ \-_]+)(\d+)(\.png)$', sample_file)
if bracket:
pfx = sample_file.split(bracket.group(0))[0]
sfx = sample_file.split(bracket.group(0))[1]
rx = re.compile(r'^' + re.escape(pfx) + r'\[(\d+)\]' + re.escape(sfx) + r'$')
pat = f"{pfx}*{sfx}"
elif dash:
pfx = dash.group(1) + dash.group(2)
sfx = dash.group(4)
rx = re.compile(r'^' + re.escape(pfx) + r'(\d+)' + re.escape(sfx) + r'$')
pat = f"{pfx}*{sfx}"
else:
# No numbering ā creation order
fns = sorted(glob.glob(os.path.join(base_dir, "*.png")), key=os.path.getctime)
if not fns:
gw.abort(f"No .png files in {base_dir}")
images = [Image.open(f).convert("RGBA") for f in fns]
return _display_and_save(images, fns, _make_outpath(pattern, output_gif, base_dir))
# Gather & sort numbered frames
items = []
for fn in glob.glob(os.path.join(base_dir, pat)):
nm = os.path.basename(fn)
m = rx.match(nm)
if m: items.append((int(m.group(1)), fn))
if not items:
gw.abort(f"No files matching pattern {pat!r}")
items.sort(key=lambda x: x[0])
fns = [fn for _, fn in items]
images = [Image.open(fn).convert("RGBA") for fn in fns]
return _display_and_save(images, fns, _make_outpath(pattern, output_gif, base_dir))