2010-05-10 79 views
46

我的目標是能夠輸入一個單詞命令並從USB附帶的根源Nexus One獲取屏幕截圖。來自adb的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 

這將創建具有隱約類似於屏幕部分一個可愛的紫色的圖像,但它絕不是一個乾淨的屏幕截圖。

回答

88

爲ICS一個容易很多解決方案是使用命令行

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

這將節省的screenshot.png文件中的當前以下目錄。

在Samsung Galaxy SII上測試& SII運行4.0.3。

+1

LoL完美男人非常感謝 – ademar111190 2012-09-05 15:34:53

+8

更快:'adb shell screencap -p \ | uuencode o | uudecode -o out.png'(需要linux + uudecode,base64也可以) – ce4 2013-01-12 11:51:09

+0

@ ce4,你應該寫出你的評論作爲答案。這是這個問題的最佳答案。 – Benjamin 2013-09-13 12:44:05

1

我相信所有的幀緩衝區最新的RGB 565,888不

7

用我的HTC Hero(因此從480x800的分辨率320x480來調整),這工作如果我使用RGB565,而不是8888:

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

是的,它適用於我的魔法/夢幻/英雄,但不適用於N1。不過謝謝。 – Marcus 2010-05-11 04:48:41

+0

也適用於SE Xperia X10。 – jurgemaister 2012-12-20 14:50:11

11

看來N1的幀緩衝區使用RGB32編碼(每像素32位)。

這裏使用的ffmpeg我的腳本:這裏介紹的方法ADP1衍生

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 

另一種方式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]) 
1

我認爲rgb32torgb888.py應該是

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

是的,我必須交換R和B通道才能從N1獲得正確的顏色。 – 2010-12-12 17:20:29

1

我希望我的腳本可能有任何用處。我在銀河選項卡上使用它,它可以很好地工作,但是您可以更改默認分辨率。它要求「zsh的」殼,雖然:

#!/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, e.g. -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.$$ 
+0

我不是很清楚 - 如果您提供解決方案,它可能(可能)在任何Android上工作。 – Patola 2011-02-16 10:55:09

1

在幻燈片的myTouch 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腳本!至少對於我的電話,沒有mogrification要正確定位爲肖像模式(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.$$ 
13

其實,還有另外一個很簡單的從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

1

rgb565代替8888也在模擬器上工作

1

有點精心/過度,但它可以同時處理screencap和framebuffer場景(以及解析分辨率)。 (它可能只是亞行的Windows版本)

#!/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 <[email protected]> 
# 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: [email protected]" 
    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

這可能與此問題相關Reading binary Data from adb shell's stdout亞行嘗試做LF到CRLF轉換爲您服務。我個人將它轉換爲\ r \ r \ n時遇到了麻煩,因此將其轉換爲[1]或使用代碼時很好。

我與運行它(在Cygwin的): adb shell 'cat /dev/graphics/fb0' | perl -pi -e 's/\r\r\n/\n/g' 似乎幫助

比其他嘗試寬度&高度比較文件的大小。如果不是這樣的話,文件大小應該被Width * height整除,然後adb工具自動爲你做事,或者它是一種更奇特的格式,然後是rgb545或rgb8888。如果它只是一個顏色問題(即:結果圖像中的所有內容都在正確的位置),那麼您可能需要考慮交換藍色通道,因爲某些系統(通常)使用字節順序BGRA而不是RGBA 。

6

如果你已經安裝了DOS2UNIX的,那麼下面的

adb shell screencap -p | dos2unix > screen.png 
+0

這是我最喜歡的方法 - 非常簡單!我爲所有文件設置了一個別名,除了文件名外,每當我需要截圖的時候都可以輕鬆使用。 – BVB 2014-02-19 21:51:22

+0

這可能只對於Windows而言是準確的,默認情況下,它將「幫助」將LF轉換爲CRLF而不使用其C運行時。在其他操作系統上,運行dos2unix會破壞png – 2017-05-10 23:46:59

1

的一種方式完全使自動化這個過程是創建一個腳本這增加了短路電流時間戳的文件名。這樣,您不必自己編寫文件名,所有屏幕截圖都有不同的名稱,並且屏幕截圖按時間排序。 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 

這將創建一個名爲像screenshot_2014-01-07-10文件:31.png

3

現在我們已經有了一個單行命令採取截圖。命令如下:

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

在終端中輸入上述命令並按回車鍵。如果要將屏幕截圖存儲在任何特定位置,請在screen.png之前提供路徑(或)目錄。

Source

+0

你應該得到一個獎品人!非常感謝!!! – 2015-05-08 03:10:51

+0

謝謝佩德羅·巴西雷羅先生。 – parthiban 2017-11-30 07:22:52