A couple of weeks ago, I was hacking on the LoL Shield with Nathan Rosenquist, when we realized that it was really time consuming to use the spreadsheet program to build animations. Never fear, a quick python script later and we could generate animations automatically from animated gifs.
Using the program, you can take black & white 14×9 GIF animations of (probably) any length, such as the following one by Nathan:
and get some code ready for the LoLing:
uint16_t ripple[][9] PROGMEM = { { 520 , 1028 , 2050 , 2050 , 2114 , 2050 , 2050 , 1028 , 520 , }, { 2050 , 4097 , 4097 , 8256 , 8352 , 8256 , 4097 , 4097 , 2050 , }, { 8192 , 8192 , 224 , 272 , 272 , 272 , 224 , 8192 , 8192 , }, { 0 , 224 , 272 , 520 , 520 , 520 , 272 , 224 , 0 , }, { 224 , 272 , 520 , 1028 , 1028 , 1028 , 520 , 272 , 224 , }, };
Here’s the python source, have fun! It requires Python and the Python Imaging Library (PIL):
#!/usr/bin/python # Python script to convert a 14x9 pixel animated gif into a format that can # be displayed on the LoLShield. # # Requires Python and the Python Imaging Library (PIL) # It would be nice if this was available using a more common language. import sys, os, Image class ImageSequence: def __init__(self, im): self.im = im def __getitem__(self, ix): try: if ix: self.im.seek(ix) return self.im except EOFError: raise IndexError # end of sequence # Open image filename = sys.argv[1] filenameBase = os.path.splitext(os.path.split(filename)[1])[0] im = Image.open(filename) # Print the variable declaration print "uint16_t " + filenameBase + "[][9] PROGMEM = {" # For each frame in the image, convert it to black & white, then into the # LoLShield format for frame in ImageSequence(im): # Convert to black and white converted = frame.convert("1") print " {", frameString = converted.tostring() # For each row in the image for row in range (0, 9): charA = ord(frameString[row*2]) charB = ord(frameString[row*2 + 1]) rowTotal = 0 # Handle the first 8 bits for col in range (0, 8): shiftAmount = 7-col rowTotal += ((charA >> shiftAmount) & 1) * 2**col # Then the next 6 for col in range (0, 6): shiftAmount = 7-col rowTotal += ((charB >> shiftAmount) & 1) * 2**(col+8) # And output the total for this row print rowTotal, ",", print "}," print "};" |
Pingback: LoL Shield Projects
Pingback: LVL1 » Blog Archive » Fun with the LOLShield
Very inspired by this. But i have a few noob questions.
Is “filename” in the python script where i would replace with the name of the GIF file I want to convert?
also where do i store the GIF file as reference? do i keep them in both arduino library and python path?
Hi Frank! Glad you like the project. Did you end up figuring it out?
The script actually looks for an image file name to be specified as a command line argument- so if you put both the script and the image in the same directory, just type this (assuming that you named the script converter.py):
./converter.py imagename.gif
And it should work. I use linux, however it should be pretty similar to get working on OS X or Windows.
Pingback: ? | We Saw a Chicken …
I got it to work under OS X, though the Imaging library was a fight.
Since Arduino uses gcc, and gcc understands binary constants, if you use Linux you can use Netpbm on the command line to avoid all this python stuff:
This outputs 9 lines of binary constants which sorta-kinda look like the image you’re displaying:
You’ll need to lop off the last comma. It’s not that much work to alter this to handle multiple frames. You may also need to play with using pnminvert (which inverts the image, so lit LEDs become dark and vice versa) and pnmflip (which mirrors the image left to right).
Haha, glad you got it working! I like the idea of using binary constants, it does make things clearer.
hey does IDE for arduino use python script? because i would like to use this quite a lot