Created
April 8, 2018 06:23
-
-
Save pnck/564eb2fa64ef91ab9ba1032a085e61f9 to your computer and use it in GitHub Desktop.
capture screen from /dev/fb0
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python2 | |
FBIOGET_VSCREENINFO = 0x4600 | |
FBIOPUT_VSCREENINFO = 0x4601 | |
FBIOGET_FSCREENINFO = 0x4602 | |
FBIOGETCMAP = 0x4604 | |
FBIOPUTCMAP = 0x4605 | |
FBIOPAN_DISPLAY = 0x4606 | |
BI_BITFIELDS = 3 | |
BI_RAW = 0 | |
__comment__ = ''' | |
struct fb_bitfield { | |
__u32 offset; /* beginning of bitfield */ | |
__u32 length; /* length of bitfield */ | |
__u32 msb_right; /* != 0 : Most significant bit is */ | |
/* right */ | |
''' | |
import os | |
import sys | |
import struct | |
from fcntl import ioctl | |
def usage(): | |
print('nothing yet..') | |
pass | |
def convert(fname): | |
from PIL import Image | |
from PIL import ImageFile | |
ImageFile.LOAD_TRUNCATED_IMAGES = True | |
with Image.open(fname) as f: | |
print('converting ' + fname + ' to png...') | |
f.save(fname[:-3] + 'png') | |
f.close() | |
print('done.') | |
os.unlink(fname) | |
def cap_fb(fname): | |
with open('/dev/fb0') as f: | |
l = list(struct.unpack( | |
'I' * 40, ioctl(f, FBIOGET_VSCREENINFO, '\x00' * 160))) | |
w = l[0] | |
h = l[1] | |
vw = l[2] | |
vh = l[3] | |
xo = l[4] | |
yo = l[5] | |
bitdepth = l[6] | |
bytesofpixel = bitdepth / 8 | |
is_color = l[7] | |
# [8:11],[11:14],[14:17],[17:20] | |
rgba_bitfields = zip(*[iter(l[8:20])] * 3) | |
print 'fb layout:', l[:7] | |
ones = int('1' * bitdepth, 2) | |
masks = struct.pack( | |
'4I', *[(ones & (~(ones << bitfield[1])) << bitfield[0]) for bitfield in rgba_bitfields]) | |
fb_memsize = vw * vh * bytesofpixel | |
raw = f.read() | |
d = raw[:fb_memsize] | |
#d = f.read(fb_memsize) | |
#open('fb_raw.save', 'wb').write(raw) | |
dd = [d[i * vw * bytesofpixel:(i + 1) * vw * bytesofpixel] | |
for i in range(vh)] # split to vh rows | |
dd = dd[yo:h + yo] # chop y | |
d = [row[xo * bytesofpixel:(w + xo) * bytesofpixel] | |
for row in dd] # chop x | |
d = ''.join(d) | |
bmp_sign = 'BM' | |
bmp_size = struct.pack('I', 0) | |
bmp_reserved = '\x00' * 4 | |
bmp_dataoff = struct.pack('I', 0) | |
#-----------14-------------------- | |
bmp_szinfohdr = struct.pack('I', 40) | |
bmp_w = struct.pack('I', w) | |
bmp_h = struct.pack('i', -h) # so i dont have to reverse all data | |
bmp_planes = struct.pack('h', 1) | |
bmp_bitcount = struct.pack('h', bitdepth) | |
# define BI_BITFIELDS 3 /* RGB bitmap with RGB masks */ | |
bmp_bicompress = struct.pack( | |
'I', {24: BI_RAW, 32: BI_RAW}.get(bitdepth, BI_BITFIELDS)) | |
bmp_imsize = struct.pack('I', fb_memsize) | |
bmp_xresolution = struct.pack('I', 0) | |
bmp_yresolution = struct.pack('I', 0) | |
bmp_colorused = struct.pack('I', 0) | |
bmp_colorsimportant = struct.pack('I', 0) | |
#--------------40---------------------- | |
#--------------mask=4*4-------------- | |
bmp_raw_h1 = bmp_sign + bmp_size + bmp_reserved + bmp_dataoff | |
bmp_raw_h2 = bmp_szinfohdr + bmp_w + bmp_h + bmp_planes + bmp_bitcount + bmp_bicompress + \ | |
bmp_imsize + bmp_xresolution + bmp_yresolution + \ | |
bmp_colorused + bmp_colorsimportant | |
if bitdepth not in (24, 32): | |
bmp_raw_h2 += masks | |
# header filled | |
# process alignment | |
align = w % 4 | |
if bitdepth != 32 and align: # dont need when bitdepth==32 | |
align = 4 - align | |
splits = [d[0 + i:w + i] for i in range(0, len(d), w)] | |
d = ''.join([p + '\x00' * align for p in splits]) | |
# re-calc size & offsets | |
bmp_dataoff = struct.pack('I', len(bmp_raw_h1) + len(bmp_raw_h2)) | |
bmp_size = struct.pack('I', len(bmp_raw_h1) + len(bmp_raw_h2) + len(d)) | |
bmp_raw_h1 = bmp_sign + bmp_size + bmp_reserved + bmp_dataoff | |
bmp_raw = bmp_raw_h1 + bmp_raw_h2 + d | |
print('saving: ' + fname) | |
with open(fname, 'wb') as ff: | |
ff.write(bmp_raw) | |
print('..OK') | |
try: | |
from PIL import Image | |
convert(fname) | |
except: | |
pass | |
if __name__ == '__main__': | |
if len(sys.argv) <= 1: # scrshot.py | |
cap_fb('scrshot_last.bmp') | |
elif sys.argv[1] == 'convert': | |
if len(sys.argv) < 3: # scrshot.py convert | |
usage() | |
else: # scrshot.py convert xx xxx xxx | |
args = sys.argv[2:] | |
for fname in args: | |
convert(fname) | |
else: # scrshot.py xxx | |
fname = sys.argv[1] | |
if sys.argv[1][-3:].lower() != 'bmp': | |
fname += '.bmp' | |
if os.path.exists(fname): | |
fname = fname[:-4] + '_2.bmp' | |
while os.path.exists(fname) : | |
fname = fname[:-4] + '_2.bmp' | |
cap_fb(fname) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment