Animated images are really popular on the web right now, especially on sites like Tumblr and Reddit. So now and then you may see something in a tv show or movie you are watching and want to create a gif from it. Using python and 'images2gif' this is very easy and this is how.
Requirements:
This isn't needed, but I am going to assume you are running on Windows.
The Plan
The plan is very simple. We are going to use FFMpeg to generate a series of screenshots from the video and then we are going resize them and stitch them together using "images2gif".
Setup the batch file to grab screenshots
FFMpeg is what we will be using to grab the screenshots and that can be called with a few command line instructions to get what we want out of it.
ffmpeg -i "Video.wmv" -ss 200 -f image2 -vframes 100 "Images//Frame%%03d.png"
- -i : The video file we want to use
- -ss : The start time we want to begin.
- -f : Output type.
- -vframes: The number of frames we want to grab
- The last argument is the output directory and file name. The %%03d will be replace by the frame number so we have a sequential list.
Have a little play with this to get a feel for how it works and then put it into a batch file.
Calling the batch file from Python
Starting with a blank python file you will want to add code like this:
import os #Create the screengrabs os.system("GrabScreenshots.bat ")
So that will write out the screenshots into a folder you have set in step one.
Using the images in python
Once the images are created you will want to load them like this
from PIL import Image #Get the file names file_names = sorted((fn for fn in os.listdir('./Images') if fn.endswith('.png'))) print file_names #Open the files print 'Opening the images' images = [Image.open('Images/' + fn) for fn in file_names]
Resizing the images
This can be done using standard PIL functions like so:
#Resize baseSize = images[0].size minheight = 192 height = baseSize[1] scale = float(height)/float(minheight) print "Scale: " + str(scale) print "Old Size: " + str(baseSize) baseSize = ( int(baseSize[0] /scale) , int(baseSize[1] /scale) ) print 'Resizing' size = baseSize; for im in images: im.thumbnail(size, Image.ANTIALIAS)
Writing out the .gif file
This is where we use the "images2gif" to create a gif from our resized images.
from images2gif import writeGif from time import time #Set to 24FPS runningtime = 0.0416 print runningtime print 'Saving' filename = "Gif/Gif" writeGif(filename + str(int(time())) + ".gif", images, duration=runningtime, dither=1, nq = 1)
I have set 0.0416 as the frame time as that is the time of one frame at 24fps. A lot of this could be controlled on input, or through a simple interface but that is a task for the reader.
This last bit of code will write out the .gif file for you to use. I would recommend playing with the settings and the size of the output image to find the desired quality and file size.
FINAL CODE
Here is all that code together with some input controls to make it easier to hook up and some cleanup at the end.
Python:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | from images2gif import writeGif from PIL import Image from time import time import os import sys #Part 1 ------------------------------- #Create the screengrabs BatFileString = "GS.bat" #Set Filename BatFileString += " AD5.wmv" #Set Start frame BatFileString += " 75" #Set Desired Number of Frames BatFileString += " 10" print BatFileString os.system(BatFileString) # Part 2 ------------------------------- #Get the file names file_names = sorted((fn for fn in os.listdir('./Images') if fn.endswith('.png'))) print file_names #Open the files print 'Opening the images' images = [Image.open('Images/' + fn) for fn in file_names] #Resize baseSize = images[0].size minheight = 192 height = baseSize[1] scale = float(height)/float(minheight) print "Scale: " + str(scale) print "Old Size: " + str(baseSize) baseSize = ( int(baseSize[0] /scale) , int(baseSize[1] /scale) ) print 'Resizing' size = baseSize; for im in images: im.thumbnail(size, Image.ANTIALIAS) #Part 3------------------------------- #Set to 24FPS runningtime = 0.0416 print runningtime print 'Saving' filename = "Gif/Gif" writeGif(filename + str(int(time())) + ".gif", images, duration=runningtime, dither=1, nq = 1) #Clean Up ----------------------------- #Remove generated images filelist = [ f for f in os.listdir('./Images') if f.endswith(".png") ] for f in filelist: os.remove('./Images/' + f) |
Bat File:
ffmpeg -i %1 -ss %2 -f image2 -vframes %3 "Images//outd%%03d.png"
And here is a link of it all together: DOWNLOAD.
Next time I look at python I will show you how this can be combined to make easily make a .gif from Youtube and other web video sites and automatically upload them to Twitter or Tumblr.