Skip to content

Instantly share code, notes, and snippets.

@kennytm
Created November 8, 2013 12:30
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kennytm/7370398 to your computer and use it in GitHub Desktop.
Save kennytm/7370398 to your computer and use it in GitHub Desktop.
Explode *.gif for Android.
#!/usr/bin/env python3
#
# explode.py --- Explode *.gif for Android
# Copyright (C) 2013 HiHex Ltd.
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program. If not, see <http://www.gnu.org/licenses/>.
'''
Explode an animated *.gif file to an <animation-list> XML file usable by Android.
'''
import PIL.Image
import PIL.ImageSequence
import argparse
import os
import os.path
import re
import sys
def main():
parser = argparse.ArgumentParser(description='Explode *.gif for Android')
parser.add_argument('-o', '--output', default='.', help='Output folder')
parser.add_argument('-p', '--use-path', action='store_true',
help='Refer to the images as path instead of drawable resource')
parser.add_argument('-x', '--xml', help='Override the name of the XML file')
parser.add_argument('gif', help='The GIF file to explode')
opt = parser.parse_args()
gif_image = PIL.Image.open(opt.gif)
output_filename = os.path.splitext(os.path.basename(opt.gif))[0]
if not opt.use_path:
# Clean filename, Android's resources require /[a-z][a-z0-9_]*/.
output_filename = re.sub('[^0-9a-z_]', '', output_filename.lower())
if not ('a' <= output_filename[:1] <= 'z'):
output_filename = 'anim_' + output_filename
os.makedirs(opt.output, exist_ok=True)
xml_name = opt.xml or output_filename + '.xml'
with open(os.path.join(opt.output, xml_name), 'w') as f:
f.write('<?xml version="1.0"?>\n')
f.write('<animation-list xmlns:android="http://schemas.android.com/apk/res/android">\n')
# TODO support non-looping gif.
for i, frame_image in enumerate(PIL.ImageSequence.Iterator(gif_image), start=1):
frame_filename = '{}_{}'.format(output_filename, i)
f.write(' <item android:drawable="')
if opt.use_path:
f.write(frame_filename)
f.write('.png')
else:
f.write('@drawable/')
f.write(frame_filename)
f.write('" android:duration="')
f.write(str(frame_image.info['duration']))
f.write('"/>\n')
frame_image.save(os.path.join(opt.output, frame_filename + '.png'))
f.write('</animation-list>')
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment