Saturday, June 12, 2010

Taking a snapshot of Android device

We can dump the framebuffer of a android device and save it as a file on our host in one single step:
  $ adb pull /dev/graphics/fb0 fb.dump
The dumped raw data is in RGB565 pixel format. So we'd like to convert it into a more common image format that could be recognized by common image viewers.
And FFMPEG could be handy for doing the conversion like this:
  $ ffmpeg -f rawvideo -pix_fmt rgb565 -s 320x480 -i fb.dump output%d.png
In this case, more than one images might be generated and named output1.png, output2.png, etc. This happens because the framebuffer on android is required to support page flipping, and the backed buffer can be dumped from the /dev/graphics/fb0 as well.

Alternatively, we can use the fbgrab utility to do the conversion:
  $ fbgrab -f fb.dump -w 320 -h 960 -b 16 output.png
Here we explicitly specify the width, height(x2 for the backed buffer), and color depth. In this case, we get a single image which is composed by two cascaded snapshots.

Of course we can also cross-compile the fbgrab utility and have it take the snapshot directly on the target device, and then pull it back with adb.
  $ fbgrab -d /dev/graphics/fb0 output.png
However, the only benefit with this, I think, is saving some time to type the dimension of the framebuffer, since the fbgrab would figure it out with IOCTL on the device node.

2 comments:

Jerimiah Baldwin said...

Excellent post! These are very insightful. I've cross-compiled the fbgrab utility for armeabi, Android. The program succeeds in creating a png for the screen and I can pull the png through adb. However, programs like windows fax and image viewer as well as Microsoft Office Picture Manager cannot show either a blank image with a black border or else simply a black image. mspaint, on the other hand, displays the image just fine.

Something wrong with the way fbgrab is writing the png? I'm interested to know what you think as you seem to be pretty competent on this subject.

Jerimiah Baldwin said...

I found that the error was that fbgrab was inverting the alpha channel. On this particular device, the alpha channel was set to FF for each pixel. Removing the alpha inversion step resolved the issue.