Adb Nexus One screenshot?

My goal is to be able to enter a command from a single word and get a screenshot from the root Nexus One connected by USB.

So far I can get the framebuffer, which, in my opinion, is a 32bit xRGB888 raw image by pulling it like this:

 adb pull /dev/graphics/fb0 fb0 

From there, however, it is difficult for me to translate it into png. I am trying with ffmpeg like this:

 ffmpeg -vframes 1 -vcodec rawvideo -f rawvideo -pix_fmt rgb8888 -s 480x800 -i fb0 -f image2 -vcodec png image.png 

This creates a beautiful purple image that has parts that vaguely resemble the screen, but it is by no means a clean screenshot.

+46
android ffmpeg graphics screenshot
May 10, '10 at 23:16
source share
14 answers

A simpler solution for ICS is to use the following commands from the command line

 adb shell /system/bin/screencap -p /sdcard/screenshot.png adb pull /sdcard/screenshot.png screenshot.png 

This will save the screenshot.png file in the current directory.

Tested on Samsung Galaxy SII and SII version 4.0.3.

+88
Aug 03 '12 at 15:43
source share

Actually there is another very simple possibility to capture a screenshot from your Android device: write a simple script 1.script as follows:

 # Imports the monkeyrunner modules used by this program from com.android.monkeyrunner import MonkeyRunner, MonkeyDevice # Connects to the current device, returning a MonkeyDevice object device = MonkeyRunner.waitForConnection() # Takes a screenshot result = device.takeSnapshot() # Writes the screenshot to a file result.writeToFile('1.png','png') 

and call monkeyrunner 1.script .

+13
Feb 16 '12 at 12:25
source share

It seems that frame buffer N1 uses RGB32 encoding (32 bits per pixel).

Here is my script using ffmpeg:

 adb pull /dev/graphics/fb0 fb0 dd bs=1920 count=800 if=fb0 of=fb0b ffmpeg -vframes 1 -vcodec rawvideo -f rawvideo -pix_fmt rgb32 -s 480x800 -i fb0b -f image2 -vcodec png fb0.png 

Another method derived from the ADP1 method described here http://code.lardcave.net/entries/2009/07/27/132648/

 adb pull /dev/graphics/fb0 fb0 dd bs=1920 count=800 if=fb0 of=fb0b python rgb32torgb888.py <fb0b >fb0b.888 convert -depth 8 -size 480x800 RGB:fb0b.888 fb0.png 

Python script 'rgb32torgb888.py':

 import sys while 1: colour = sys.stdin.read(4) if not colour: break sys.stdout.write(colour[2]) sys.stdout.write(colour[1]) sys.stdout.write(colour[0]) 
+11
Jul 19 '10 at 13:25
source share

Using my HTC Hero (and therefore setting from 480x800 to 320x480), this works if I use rgb565 instead of 8888:

 ffmpeg -vframes 1 -vcodec rawvideo -f rawvideo -pix_fmt rgb565 -s 320x480 -i fb0 -f image2 -vcodec png image.png 
+7
May 10 '10 at 23:31
source share

If you have dos2unix installed, below

 adb shell screencap -p | dos2unix > screen.png 
+6
Dec 02 '13 at 19:42
source share

Now we have one line to take a screenshot. The command is as follows:

 adb shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > screen.png 

Enter the above command into your terminal and press enter. If you want the screenshot to be saved in any particular place, specify the path (or) screen.png to screen.png .

Source

+3
Mar 10 '15 at 8:53
source share

I believe that all framebuffers are currently RGB 565, not 888.

+1
May 10 '10 at 23:29
source share

I think rgb32torgb888.py should be

  sys.stdout.write(colour[0]) sys.stdout.write(colour[1]) sys.stdout.write(colour[2]) 
+1
Oct 26 '10 at 8:47
source share

Hope my script could be helpful. I use it on the Galaxy tab and it works fine, but you can change the default resolution. This requires the zsh shell:

 #!/bin/zsh # These settings are for the galaxy tab. HRES=600 VRES=1024 usage() { echo "Usage: $0 [ -p ] outputfile.png" echo "-- takes screenshot off your Galaxy Tab Android phone." echo " -p: portrait mode" echo " -r X:Y: specify resolution, eg -r 480:640 specifies that your cellphone has 480x640 resolution." exit 1 } PORTRAIT=0 # false by default umask 022 [[ ! -w . ]] && { echo "*** Error: current directory not writeable." usage } [[ ! -x $(which mogrify) ]] && { echo "*** Error: ImageMagick (mogrify) is not in the PATH!" usage } while getopts "pr:" myvar do [[ "$myvar" == "p" ]] && PORTRAIT=1 [[ "$myvar" == "r" ]] && { testhres="${OPTARG%%:*}" # remove longest-matching :* from end testvres="${OPTARG##*:}" # remove longest-matchung *: from beginning if [[ $testhres == <0-> && $testvres == <0-> ]] # Interval: from 0 to infinite. Any value would be: <-> then HRES=$testhres VRES=$testvres else echo "Error! One of these values - '${testhres}' or '${testvres}' - is not numeric!" usage fi } done shift $((OPTIND-1)) [[ $# < 1 ]] && usage outputfile="${1}" blocksize=$((HRES*4)) count=$((VRES)) adb pull /dev/graphics/fb0 fb0.$$ /bin/dd bs=$blocksize count=$count if=fb0.$$ of=fb0b.$$ /usr/bin/ffmpeg -vframes 1 -vcodec rawvideo -f rawvideo -pix_fmt rgb32 -s ${VRES}x${HRES} -i fb0b.$$ -f image2 -vcodec png "${outputfile}" if (( ${PORTRAIT} )) then mogrify -rotate 270 "${outputfile}" else mogrify -flip -flop "${outputfile}" fi /bin/rm -f fb0.$$ fb0b.$$ 
+1
Feb 16 2018-11-11T00:
source share

On MyTouch Slide 3G, I ended up with red and blue channels that changed my screenshots. Here's the correct ffmpeg spell for someone else in this situation: (noteworthy part: -pix_fmt bgr32 )

 ffmpeg -vframes 1 -vcodec rawvideo -f rawvideo -pix_fmt bgr32 -s 320x480 -i fb0 -f image2 -vcodec png image.png 

Thanks Patola for a convenient shell script! At least for my phone, for proper orientation in portrait mode (320x480), no cleaning is required, and therefore the end of its script becomes:

 # assuming 'down' is towards the keyboard or usb jack # in landscape and protrait modes respectively (( ${PORTRAIT} )) || mogrify -rotate 270 "${outputfile}" /bin/rm -f fb0.$$ fb0b.$$ 
+1
May 04 '11 at 5:20 a.m.
source share

rgb565 instead of 8888 also work on an emulator

+1
Jun 07 2018-12-12T00:
source share

A bit complicated / excessive, but it handles the screencap and framebuffer scripts (and also calculates the resolution).

 #!/bin/bash # # adb-screenshot - simple script to take screenshots of android devices # # Requires: 'ffmpeg' and 'adb' to be somewhere in the PATH # # Author: Kevin C. Krinke <kevin@krinke.ca> # License: Public Domain # globals / constants NAME=$(basename $0) TGT=~/Desktop/${NAME}.png SRC=/sdcard/${NAME}.png TMP=/tmp/${NAME}.$$ RAW=/tmp/${NAME}.raw FFMPEG=$(which ffmpeg) ADB=$(which adb) DD=$(which dd) USB_DEVICE="" # remove transitory files if exist function cleanup () { [ -f "${RAW}" ] && rm -f "${RAW}" [ -f "${TMP}" ] && rm -f "${TMP}" [ -z "$1" ] && die "aborting process now." exit 0 } # exit with an error function die () { echo "Critical Error: $@" exit 1 } # catch all signals and cleanup / dump trap cleanup \ SIGHUP SIGINT SIGQUIT SIGILL SIGTRAP SIGABRT SIGEMT SIGFPE \ SIGKILL SIGBUS SIGSEGV SIGSYS SIGPIPE SIGALRM SIGTERM SIGURG \ SIGSTOP SIGTSTP SIGCONT SIGCHLD SIGTTIN SIGTTOU SIGIO SIGXCPU \ SIGXFSZ SIGVTALRM SIGPROF SIGWINCH SIGINFO SIGUSR1 SIGUSR2 # adb is absolutely required [ -x "${ADB}" ] || die "ADB is missing!" # cheap getopt while [ $# -gt 0 ] do case "$1" in "-h"|"--help") echo "usage: $(basename $0) [-h|--help] [-s SERIAL] [/path/to/output.png]" exit 1 ;; "-s") [ -z "$2" ] && die "Missing argument for option \"-s\", try \"${NAME} --help\"" HAS_DEVICE=$(${ADB} devices | grep "$2" ) [ -z "${HAS_DEVICE}" ] && die "No device found with serial $2" USB_DEVICE="$2" ;; *) [ -n "$1" -a -d "$(dirname $1)" ] && TGT="$1" ;; esac shift done # prep target with fire [ -f "${TGT}" ] && rm -f "${TGT}" # tweak ADB command line if [ -n "${USB_DEVICE}" ] then ADB="$(which adb) -s ${USB_DEVICE}" fi # calculate resolution DISPLAY_RAW=$(${ADB} shell dumpsys window) HRES=$(echo "${DISPLAY_RAW}" | grep SurfaceWidth | head -1 | perl -pe 's/^.*\bSurfaceWidth\:\s*(\d+)px\b.*$/$1/') VRES=$(echo "${DISPLAY_RAW}" | grep SurfaceHeight | head -1 | perl -pe 's/^.*\bSurfaceHeight\:\s*(\d+)px\b.*$/$1/') RES=${HRES}x${VRES} # check for screencap binary HAS_SCREENCAP=$(${ADB} shell "[ -x /system/bin/screencap ] && echo 1 || echo 0" | perl -pe 's/\D+//g') if [ "$HAS_SCREENCAP" == "1" ] then # use screencap to get the image easy-peasy echo -n "Getting ${RES} screencap... " ( ${ADB} shell /system/bin/screencap ${SRC} 2>&1 ) > /dev/null [ "$?" != "0" ] && die "Failed to execute screencap" ( ${ADB} pull ${SRC} ${TMP} 2>&1 ) > /dev/null [ "$?" != "0" ] && die "Failed to pull png image" ( ${ADB} shell rm ${SRC} 2>&1 ) > /dev/null [ "$?" != "0" ] && die "Failed to remove png image" mv ${TMP} ${TGT} echo "wrote: ${TGT}" else # fetch a framebuffer snapshot # ffmpeg is only needed if device is pre-ICS [ -x "${FFMPEG}" ] || die "FFMPEG is missing!" [ -x "${DD}" ] || die "DD is missing!" echo -n "Getting ${RES} framebuffer... " ( ${ADB} pull /dev/graphics/fb0 ${RAW} 2>&1 ) > /dev/null [ "$?" != "0" ] && die "Failed to pull raw image data" # calculate dd parameters COUNT=$((HRES*4)) BLOCKSIZE=$((VRES)) ( ${DD} bs=${BLOCKSIZE} count=${COUNT} if=${RAW} of=${TMP} 2>&1 ) > /dev/null [ "$?" != "0" ] && die "Failed to realign raw image data" ( ${FFMPEG} -vframes 1 -vcodec rawvideo -f rawvideo -pix_fmt rgb32 -s ${RES} -i ${TMP} -f image2 -vcodec png ${TGT} 2>&1 ) > /dev/null [ "$?" != "0" ] && die "Failed to encode PNG image" echo "wrote: ${TGT}" fi # exit app normal cleanup 1 
+1
02 Oct. '12 at 5:50
source share

This may be due to the problem of reading binary data from the add shell stdout , where adb is trying to convert LF to CRLF for you (this is probably just the version of Windows ADB). I personally had problems converting \ n to \ r \ r \ n in order to somehow convert this well, either for using the code in [ 1 ] or for using.

for me it starts with (in cygwin): adb shell 'cat /dev/graphics/fb0' | perl -pi -e 's/\r\r\n/\n/g' adb shell 'cat /dev/graphics/fb0' | perl -pi -e 's/\r\r\n/\n/g' seemed to help

besides this, try comparing the width and height with the file size. The file size should be evenly divisible by Width * height , if it is not, either the adb tool automatically does things for you, or a more exotic format than rgb545 or rgb8888.

if this is only a color issue (that is: everything in the result image is in the right place), then you can consider replacing the Red and Blue channels, as some systems (in general) use the BGRA byte order instead of RGBA.

+1
Jul 14 '13 at 5:31 on
source share

A way to fully automate this process is to create a script that adds the current timestamp to the file name. Thus, you do not need to write the file name yourself, all your screenshots have a different name, and your screenshots are sorted by time.

Example bash script:

 #! /bin/bash filename=$(date +"_%Y-%m-%d-%H:%M") /PATH_TO_ANDROID_SDK/platform-tools/adb -d shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > screenshot$filename.png 

This will create a file called screenshot_2014-01-07-10: 31.png

+1
Jan 07 '14 at 9:58
source share



All Articles