从adb Nexus One的屏幕截图?

我的目标是能够input一个单词的命令,并从USB连接的根源Nexus One截图。

到目前为止,我可以通过拉动它来获得我认为是32bit xRGB888原始图像的帧缓冲区:

 adb pull /dev/graphics/fb0 fb0 

从那里,我很难得到它转换为PNG。 我试图用ffmpeg像这样:

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

这创造了一个可爱的紫色图像,其中有一些模糊的部分,但它绝不是一个干净的截图。

ICS的一个更简单的解决scheme是从命令行使用以下命令

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

这会将screenshot.png文件保存在当前目录中。

在运行4.0.3的Samsung Galaxy SII&SII上testing。

其实,从你的android设备抓取截图还有另外一个非常简单的能力:写简单的脚本1.script是这样的:

 # 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') 

并且调用monkeyrunner 1.script

看来N1的帧缓冲区使用RGB32编码(每像素32位)。

这是我的脚本使用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 

从这里描述的ADP1方法衍生的另一种方法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脚本“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]) 

使用我的HTC Hero(从而调整从480×800到320×480),如果我使用rgb565而不是8888,

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

如果你已经安装了dos2unix,那么下面

 adb shell screencap -p | dos2unix > screen.png 

现在我们有一个单行命令来截图。 命令如下:

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

在terminal上键入上述命令,然后按回车键。 如果你想截图存储在任何特定的位置,然后给screen.png之前的path(或)目录。

来源 。

我相信迄今为止所有的帧缓冲器都是RGB 565,而不是888。

我认为应该是rgb32torgb888.py

  sys.stdout.write(colour[0]) sys.stdout.write(colour[1]) sys.stdout.write(colour[2]) 

我希望我的脚本可能有任何用处。 我在我的星系选项卡上使用它,它完美的工作,但它可以让你改变默认的分辨率。 但是它需要“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.$$ 

在MyTouch Slide 3G上,我截取了红色和蓝色的频道。 在这种情况下,对于其他人来说,这是正确的ffmpeg咒语:(着名的部分: -pix_fmt bgr32

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

感谢Patola提供便利的shell脚本! 至less对于我的手机来说,没有必要正确定位纵向模式(320×480),所以脚本的结尾是:

 # 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.$$ 

rgb565而不是8888也可以在仿真器上工作

有点复杂/过度,但是它可以处理screencap和framebuffer场景(以及parsing分辨率)。

 #!/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 

这可能与问题有关, 从adb shell的stdout中读取二进制数据 ,adb试图为你做LF到CRLF的转换(它可能只是adb的windows版本)。 我个人遇到麻烦,将其转换为\ r \ r \ n,以便将其转换为使用[ 1 ]中的代码或使用代码。

对于我运行(在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'似乎有帮助

除了那个尝试比较宽度和高度的文件的大小。 如果不是这样的话,文件大小应该可以被Width * height整除,然后adb工具会自动为你做事情,或者是一个更为奇特的格式,然后是rgb545或者rgb8888。

如果这只是一个颜色问题(即:结果图像中的所有内容都在正确的位置),那么您可能需要考虑交换红色和蓝色通道,因为一些系统(通常)使用字节顺序BGRA而不是RGBA。

一种完全自动化这个过程的方法是创build一个脚本,将curent时间戳添加到文件名。 这样,你不必自己写文件名,所有的屏幕截图都有不同的名称,而且屏幕截图按时间sorting。

bash脚本示例:

 #! /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 

这将创build一个名为screenshot_2014-01-07-10:31.png的文件