Abhinav Singh
Abhinav Singh

Reputation: 2651

What format does "adb screencap /sdcard/screenshot.raw" produce? (without "-p" flag)

I am looking to use adb screencap utility without the -p flag. I imagined output will be dumped in raw format, but doesn't look like it. My attempts of opening the raw image file with Pillow (python) library resulted in:

$ adb pull /sdcard/screenshot.raw screenshot.raw
$ python
>>> from PIL import Image
>>> Image.open('screenshot.raw')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/....../lib/python2.7/site-packages/PIL/Image.py", line 2025, in open
    raise IOError("cannot identify image file")
IOError: cannot identify image file

Found out not the right way to read raw images like this, I even gave the following a shot: How to read a raw image using PIL?

>>> with open('screenshot.raw', 'rb') as f:
...     d = f.read()
... 
>>> from PIL import Image
>>> Image.frombuffer('RGB', len(d), d)
__main__:1: RuntimeWarning: the frombuffer defaults may change in a future release; for portability, change the call to read:
  frombuffer(mode, size, data, 'raw', mode, 0, 1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/..../lib/python2.7/site-packages/PIL/Image.py", line 1896, in frombuffer
    return frombytes(mode, size, data, decoder_name, args)
  File "/Users/..../lib/python2.7/site-packages/PIL/Image.py", line 1821, in frombytes
    im = new(mode, size)
  File "/Users/..../lib/python2.7/site-packages/PIL/Image.py", line 1787, in new
    return Image()._new(core.fill(mode, size, color))
TypeError: must be 2-item sequence, not int

All possible mode option lead to same TypeError exception.

Here is what hexdump utility reveals:

$ hexdump -C img.raw | head
00000000  d0 02 00 00 00 05 00 00  01 00 00 00 1e 1e 1e ff  |................|
00000010  1e 1e 1e ff 1e 1e 1e ff  1e 1e 1e ff 1e 1e 1e ff  |................|
*
000038c0  1e 1e 1e ff 1e 1e 1e ff  21 21 21 ff 2b 2b 2b ff  |........!!!.+++.|
000038d0  1e 1e 1e ff 1e 1e 1e ff  1e 1e 1e ff 1e 1e 1e ff  |................|
*
00004400  1e 1e 1e ff 1e 1e 1e ff  47 47 47 ff 65 65 65 ff  |........GGG.eee.|
00004410  20 20 20 ff 1e 1e 1e ff  1e 1e 1e ff 1e 1e 1e ff  |   .............|
00004420  1e 1e 1e ff 1e 1e 1e ff  1e 1e 1e ff 1e 1e 1e ff  |................|
*

On osx:

$ file screenshot.raw 
screenshot.raw: data

screencap help page doesn't reveal much either about format of output data without -p flag:

$ adb shell screencap -h
usage: screencap [-hp] [FILENAME]
   -h: this message
   -p: save the file as a png.
If FILENAME ends with .png it will be saved as a png.
If FILENAME is not given, the results will be printed to stdout.

Upvotes: 10

Views: 8830

Answers (3)

Argentum
Argentum

Reputation: 93

To read adb screencap raw format in python:

from PIL import Image
Image.frombuffer('RGBA', (1920, 1080), raw[12:], 'raw', 'RGBX', 0, 1)

The most important part is skipping the header, as mentioned in @Emmanuel's answer

Note that (1920, 1080) are your device resolution which can be obtained with

adb shell wm size

Hopefully this will save someone 12 hours investigating why cv2.matchTemplate has different match on almost identical images.

Upvotes: 5

Enyby
Enyby

Reputation: 4420

Format:

  • 4 bytes as uint32 - width
  • 4 bytes as uint32 - height
  • 4 bytes as uint32 - pixel format
  • (width * heigth * bytespp) bytes as byte array - image data, where bytespp is bytes per pixels and depend on pixel format. Usually bytespp is 4.

Info from source code of screencap.

For your example:

00000000  d0 02 00 00 00 05 00 00  01 00 00 00 1e 1e 1e ff
  • d0 02 00 00 - width - uint32 0x000002d0 = 720
  • 00 05 00 00 - height - uint32 0x00000500 = 1280
  • 01 00 00 00 - pixel format - uint32 0x00000001 = 1 = PixelFormat.RGBA_8888 => bytespp = 4 => RGBA
  • 1e 1e 1e ff - first pixel data - R = 0x1e; G = 0x1e; B = 0x1e; A = 0xff;

Pixels with data stored in array of bytes with size 720*1280*4.

Upvotes: 19

Emmanuel Devaux
Emmanuel Devaux

Reputation: 3407

Thanks to the extract of your file , I guess your raw file is formated as width x height then the whole set of RGBA pixels (32 bits) (width x height times) Here I see you get a 720x1280 image captured..

May the ImageMagick toolset help you to view/convert it in a more appropriate file format. Here below a sample that may help you (ImageMagick convert command, for osx see http://cactuslab.com/imagemagick/ )

# skip header info  
dd if=screenshot.raw of=screenshot.rgba skip=12 bs=1
# convert rgba to png
convert -size 720x1280 -depth 8 screenshot.rgba screenshot.png

If it doesn't work you may try changing skip=12 by skip=8 and/or 720x1280 by 1280x720 ..

Hope that help

Upvotes: 7

Related Questions