Wednesday, July 07, 2010

Going really 8-bit

Back when I was a kid, my nerd friends and I would create graphics for our Commodore computers by filling filling in squares on graph paper and calculating the bitmaps. A single character on the Commodore 64 and Vic 20 was an 8x8 grid.

I recently found an 8-bit image fondly remembered from my youth, the Intellivision Running Man, in animated GIF format. I converted the GIF to a short video, which I embedded in a video project.

Some of my video conversion notes were covered in another post and some are on my wiki.

I want to extract the Intellivision Running Man bitmaps for use in an opengl project that I'm thinking about doing. Though it would probably be simpler for me to just sit down with pen and paper to graph and calculate the bitmaps, I'm hoping to find tools that will allow me to extract the data directly from raw video.

I first needed to reduce the screen resolution as much as possible by shrinking the video and dropping frames. Here I shrank the video output to 24x24 and reduced the frame rate to 4 frames per second.

ffmpeg -i intel.avi -r 4 -s 24x24 intel8bit.avi

Next I extracted individual bitmap images:

ffmpeg -i intel8bit.avi -f image2 foo_%5d.bmp

I initially took one image into Gimp and used Desaturate to convert it to grayscale, and then I used Levels to reduce image to pure Black or White. But I didn't want to repeat this again and again. So I wrote a small Python script which achieved the same goal and along the way got to play with the PIL library, which I've not used before.


from PIL import Image
import sys, os

def bw(pt):
if pt>126:
return 255
else:
return 0

for infile in sys.argv[1:]:
f, e = os.path.splitext(infile)
outfile = f + "_mod" + e

im = Image.open(infile)

im = im.convert('L')
out = im.point(bw)

out.save(outfile)
print outfile


This little script loads a bitmap then uses convert() with the 'L' option to make it grayscale. (I couldn't find a comprehensive list of options for convert---the documentation could use some work.)

Finally, I used the point method that passes each pixel in the bitmap data to a custom function. Your function can do anything, but mine just looks at the value, makes higher level grays absolute black and lower level grays absolute white. point() returns a copy of the bitmap file (headers updated and intact) with the transformed result, which is then saved.

At this point I have true black and white bitmaps.

I wanted to quickly visualize my bitmap, to get a feel for how much more I want to reduce the size of my bitmaps. This little script renders my images to screen as a series of X's.


from PIL import Image
import sys, os


for infile in sys.argv[1:]:

im = Image.open(infile)
data = im.getdata()
for idx in range (0, len(data)):
i = data[idx]
if i == 255:
print 'X',
else:
print ' ',

if (idx+1) % 24 == 0:
print ''



The output looks like this:


devin@studio:~/src/py$ python showdata.py /home/devin/Video/bitmaps/foo_00041_mod.bmp

X X X X X X X X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X
X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X X X X X X
X X X X X X X X X X X X X X X X X X X X X X X X

2 comments:

玉苓玉苓 said...
This comment has been removed by a blog administrator.
JasonBirk佳琪 said...
This comment has been removed by a blog administrator.