Skip to content

Instantly share code, notes, and snippets.

@commonsguy
Last active May 1, 2023 14:26
Show Gist options
  • Save commonsguy/6757059 to your computer and use it in GitHub Desktop.
Save commonsguy/6757059 to your computer and use it in GitHub Desktop.
Ruby script to convert animated GIF into an Android AnimationDrawable
#!/usr/bin/ruby
require 'fileutils'
require 'RMagick'
require 'slop'
require 'builder'
opts = Slop.new do
banner "gif2animdraw [options]\n"
on :i, :input=, 'path to animated GIF (or directory of GIFs)', :required => true
on :o, :outdir=, 'path to root output directory', :required => true
on :d, :density=, 'density name to use for frames', :required=>true
on :oneshot, 'if set, animation does not repeat', :required => false, :default=>false
help
end
begin
opts.parse
rescue
puts opts.help
exit -1
end
if !['ldpi', 'mdpi', 'tvdpi', 'hdpi', 'xhdpi', 'xxhdpi', 'xxxhdpi'].include?(opts[:d])
puts "Invalid density #{opts[:d]}"
exit -1
end
glob=File.directory?(opts[:i]) ? File.join(opts[:i], '*.gif') : opts[:i]
Dir[glob].each do |gif|
input=Magick::ImageList.new(gif).coalesce
output=File.join(opts[:o], 'drawable')
output_density=File.join(opts[:o], 'drawable-'+opts[:d])
basename=File.basename(gif, '.gif').downcase.gsub(/\W/,'_')
FileUtils.mkdir_p output
FileUtils.mkdir_p output_density
Dir.glob(File.join(output_density, basename+'*.png')).each {|f| File.delete(f) }
input.write File.join(output_density, basename+'_%d.png')
builder = Builder::XmlMarkup.new(:indent=>2)
builder.tag!('animation-list',
'xmlns:android'=>'http://schemas.android.com/apk/res/android',
'android:oneshot'=>opts[:oneshot]) do
i=0
input.each do |frame|
builder.item('android:drawable'=>"@drawable/#{basename}_#{i}",
'android:duration'=>frame.delay*1000/input.ticks_per_second)
i+=1
end
end
open(File.join(output, basename+'.xml'), 'w') do |f|
f.puts builder.target!
end
end
@commonsguy
Copy link
Author

I wrote a blog post that doubles as semi-documentation for this script.

@ladoleste
Copy link

Call me lazy, but I'm looking forward to "a Web front end on this functionality" :)

@frankkienl
Copy link

Is there a way to convert all the gif-files in a folder?
I have 158 folders with about 12 gif each to convert...
https://github.com/frankkienl/BronyLiveWallpaper/tree/master/BronyLiveWallpaper/src/main/assets

Btw, I'm not using a WebView, but this library:
https://code.google.com/p/android-gifview/
Its okay, I guess, bit memory-hungry.
But your solution sounds a lot better ;-)

@commonsguy
Copy link
Author

@frankkienl: I updated the script so -i accepts a directory or an individual GIF.

And, since comments here do not trigger GitHub notifications (grrrrr...), please use StackOverflow for further questions about this script. Tag your question with commonsware (in addition to android or ruby, whichever is more applicable to your question).

@nateridderman-lilly
Copy link

If anyone else is still looking at this (no judgements), make sure you install slop 3, not the rewritten slop 4 which was rewritten and has broken changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment