私の目標は、1つのWordコマンドを入力し、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の非常に簡単なソリューションは、コマンドラインから次を使用することです
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でテスト済み。
実際、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を使用して(したがって、480x800から320x480に調整します)、8888の代わりにrgb565を使用すると、これは機能します。
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
これまでのすべてのフレームバッファは、888ではなくRGB 565だと思います。
これで、スクリーンショットを撮る1行のコマンドができました。コマンドは次のとおりです。
adb Shell screencap -p | Perl -pe 's/\x0D\x0A/\x0A/g' > screen.png
端末に上記のコマンドを入力し、Enterキーを押します。スクリーンショットを特定の場所に保存する場合は、screen.png
の前にパス(または)ディレクトリを指定します。
ソース 。
少し手の込んだ/過剰ですが、screencapとframebufferの両方のシナリオを処理します(解像度も把握します)。
#!/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: $@"
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
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に感謝します!少なくとも私の携帯電話では、ポートレートモード(320x480)に正しく方向を合わせるために変形を行う必要はありません。したがって、彼のスクリプトの終わりは次のようになります。
# 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
エミュレーターでも動作します
これは、問題に関連している可能性があります adbシェルのstdoutからバイナリデータを読み取る adbが行うことを試みるLFからCRLFへの変換(おそらく、adbの単なるWindowsバージョンです) )。個人的には\ nから\ 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よりもエキゾチックな形式になります。
それが単なる色の問題である場合(つまり、結果画像のすべてが正しい場所にある場合)、一部のシステム(一般的に)はRGBAではなくBGRAを使用するため、赤と青のチャンネルを交換することを検討できます。
このプロセスを完全に自動化する方法は、現在のタイムスタンプをファイル名に追加するスクリプトを作成することです。このように、ファイル名を自分で記述する必要はありません。すべてのスクリーンショットは異なる名前を持ち、スクリーンショットは時間でソートされます。
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のような名前のファイルが作成されます
私のスクリプトが役に立つことを願っています。 galaxyタブで使用し、完全に機能しますが、デフォルトの解像度を変更することは可能です。ただし、「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.$$
Rgb32torgb888.pyは
sys.stdout.write(colour[0])
sys.stdout.write(colour[1])
sys.stdout.write(colour[2])