Android uses the C language to read fb0 for screenshots, and saves it as the BMP of rgb565

Source: Internet
Author: User

Source code: http://download.csdn.net/detail/victoryckl/4074654

Source code of an enhanced version: screenshots are taken through fb0 operations, and images are sent to fb0. rgb565 rgb888 is supported.
BMP and fb0 in xrgb8888 format

In Android, fb0 is read in C language for screenshots and saved as BMP images,

Data in 16-bit (rgb565) and 24-bit (rbg888) formats can be verified on the android2.2 and 4.0 simulators.

Screen capture mainly involves reading screen data and generating images.

1. Read screen data

Enable the video memory device/dev/graphics/fb0 in read-only mode, and then map the Shared Mode (map_shared) to a piece of memory through MMAP, you can directly read screen data in memory elsewhere.

Note that the size of the Virtual Display Device of fb0 is greater than that of the actual screen display device. During MMAP ing, you must map the virtual size installed. Otherwise, screenshots may fail.

The main code for the video memory device:

/********************************************************************created:2012/02/07filename: myfb.cauthor:purpose:*********************************************************************/#ifndef WIN32//-------------------------------------------------------------------#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <fcntl.h>#include <sys/mman.h>#include <sys/stat.h>#include <sys/types.h>#include <linux/fb.h>#include <linux/kd.h>struct FB {    unsigned short *bits;    unsigned size;    int fd;    struct fb_fix_screeninfo fi;    struct fb_var_screeninfo vi;};int fb_bpp(struct FB *fb){if (fb) {return fb->vi.bits_per_pixel;}return 0;}int fb_width(struct FB *fb){if (fb) {return fb->vi.xres;}return 0;}int fb_height(struct FB *fb){if (fb) {return fb->vi.yres;}return 0;}int fb_size(struct FB *fb){if (fb) {unsigned bytespp = fb->vi.bits_per_pixel / 8;return (fb->vi.xres * fb->vi.yres * bytespp);}return 0;}int fb_virtual_size(struct FB *fb){if (fb) {unsigned bytespp = fb->vi.bits_per_pixel / 8;return (fb->vi.xres_virtual * fb->vi.yres_virtual * bytespp);}return 0;}void * fb_bits(struct FB *fb){unsigned short * bits = NULL;if (fb) {int offset, bytespp;bytespp = fb->vi.bits_per_pixel / 8;/* HACK: for several of our 3d cores a specific alignment* is required so the start of the fb may not be an integer number of lines* from the base.  As a result we are storing the additional offset in* xoffset. This is not the correct usage for xoffset, it should be added* to each line, not just once at the beginning */offset = fb->vi.xoffset * bytespp;offset += fb->vi.xres * fb->vi.yoffset * bytespp;bits = fb->bits + offset / sizeof(*fb->bits);}return bits;}void fb_update(struct FB *fb){if (fb) {fb->vi.yoffset = 1;ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi);fb->vi.yoffset = 0;ioctl(fb->fd, FBIOPUT_VSCREENINFO, &fb->vi);}}static int fb_open(struct FB *fb){if (NULL == fb) {return -1;}    fb->fd = open("/dev/graphics/fb0", O_RDONLY);    if (fb->fd < 0) {printf("open(\"/dev/graphics/fb0\") failed!\n");        return -1;}    if (ioctl(fb->fd, FBIOGET_FSCREENINFO, &fb->fi) < 0) {printf("FBIOGET_FSCREENINFO failed!\n");        goto fail;}    if (ioctl(fb->fd, FBIOGET_VSCREENINFO, &fb->vi) < 0) {printf("FBIOGET_VSCREENINFO failed!\n");        goto fail;}    fb->bits = mmap(0, fb_virtual_size(fb), PROT_READ, MAP_SHARED, fb->fd, 0);    if (fb->bits == MAP_FAILED) {printf("mmap() failed!\n");        goto fail;}    return 0;fail:    close(fb->fd);    return -1;}static void fb_close(struct FB *fb){if (fb) {munmap(fb->bits, fb_virtual_size(fb));close(fb->fd);}}static struct FB g_fb;struct FB * fb_create(void){memset(&g_fb, 0, sizeof(struct FB));if (fb_open(&g_fb)) {return NULL;}return &g_fb;}void fb_destory(struct FB *fb){fb_close(fb);}//-------------------------------------------------------------------#endif//#ifndef WIN32

2. generate an image

The generated image is in BMP format. You can automatically generate 16-bit (rgb565) and 24-bit (rbg888) images based on the number of pixels of the device.

The main task is to correctly fill in the file header information of BMP, 24-bit (rbg888) is relatively simple.

The 16-bit (rgb565) is more complex. The value of the bicompression member must be bi_bitfields. The first three positions of the original color palette are occupied by three DWORD variables, which are called Red, green, and blue masks, in the 565 format, they are 0xf800, 0x07e0, and 0x001f.

In addition, Windows requires that the file size be a multiple of 4. The file size must be correctly displayed only after the following processing is performed.

head->bfSize = head->bfOffBits + size;head->bfSize = (head->bfSize + 3) & ~3;size = head->bfSize - head->bfOffBits;

Main Code for generating images:

/*************************************** * **************************** Created: 2012/02/07 filename: savebmp. cauthor: Purpose: **************************************** * ****************************/# include <stdlib. h> # include <stdio. h> # include <memory. h> // bitmap/* structure of the bitmap file name Bitmap header bitmapfileheader bmfh bitmap information header (Bitmap-in) Formation header) bitmapinfoheader bmih color table (color table) rgbquad acolors [] Byte abitmapbits [] */typedef struct BMP _header {short twobyte; // two bytes, these two characters cannot be written to the file. // 14 bchar bftype [2]; //! File type. The value must be 0x4d42, that is, the character 'bm 'unsigned int bfsize ;//! Indicates the file size, in bytes: Unsigned int bfreserved1; // reserved, must be set to 0 unsigned int bfoffbits ;//! The Byte offset between the file header and the actual image data. Here it is 14B + sizeof (BMP info)} bmpheader; typedef struct BMP _info {// 40 bunsigned int bisize ;//! The number of words required for the bmp info structure int biwidth ;//! The image width, in pixels, int biheight ;//! The image width, in pixels. If the value is positive, it indicates that the image is backward. If the value is negative, it is positive unsigned short biplanes ;//! The number of description bits of the target device. The value will always be set to 1 unsigned short bibitcount ;//! Number of BITs/pixels. The value is 1, 4, 8, 16, 24, or 32 unsigned int bicompression; // description of the image data compression type # define bi_rgb 0l // No compression # define bi_rle8 1l // RLE compression encoding of 8 bits per pixel, the compression format consists of 2 bytes (repeated pixel counts and color indexes); # define bi_rle4 2L // RLE compression encoding of 4 bits per pixel, the compression format consists of 2 bytes # define bi_bitfields 3l // the bit of each pixel is determined by the specified mask. Unsigned int bisizeimage; // the size of the image, in bytes. When bi_rgb format is used, it can be set to 0int bixpelspermeter; // horizontal resolution. The pixel/meter is used to represent int biypelspermeter; // The vertical resolution. The pixel/meter is used to represent unsigned int biclrused; // The number of color indexes in the color table used by the bitmap (if it is set to 0, all color palette items are used) unsigned int biclrimportant; // The number of color indexes that have an important impact on image display. If it is 0, it means it is important .} BMP Info; typedef struct detail {unsigned char rgbblue; unsigned char rgbgreen; unsigned char rgbred; unsigned char character;} percent; typedef struct tagbitmapinfo {BMP info bmiheader; // rgbquad bmicolors [1]; unsigned int RGB [3];} bitmapinfo; static int get_rgb888_header (int w, int H, bmpheader * head, BMP info * info) {int size = 0; if (Head & info) {size = W * H * 3; memset (Head, 0, sizeof (* head )); Memset (Info, 0, sizeof (* info); head-> bftype [0] = 'B'; head-> bftype [1] = 'M '; head-> bfoffbits = 14 + sizeof (* info); head-> bfsize = head-> bfoffbits + size; head-> bfsize = (Head-> bfsize + 3 )&~ 3; // for windows, the file size must be a multiple of 4: size = head-> bfsize-head-> bfoffbits; Info-> bisize = sizeof (BMP info ); info-> biwidth = W; Info-> biheight =-H; Info-> biplanes = 1; Info-> bibitcount = 24; Info-> bicompression = bi_rgb; info-> bisizeimage = size; printf ("rgb888: % dbit, % d * % d, % d \ n", info-> bibitcount, W, H, head-> bfsize);} return size;} static int get_rgb565_header (int w, int H, bmpheader * head, bitmapinfo * info) {int size = 0; If (Head & info) {size = W * H * 2; memset (Head, 0, sizeof (* head); memset (Info, 0, sizeof (* info); head-> bftype [0] = 'B'; head-> bftype [1] = 'M '; head-> bfoffbits = 14 + sizeof (* info); head-> bfsize = head-> bfoffbits + size; head-> bfsize = (Head-> bfsize + 3 )&~ 3; size = head-> bfsize-head-> bfoffbits; Info-> bmiheader. bisize = sizeof (Info-> bmiheader); Info-> bmiheader. biwidth = W; Info-> bmiheader. biheight =-H; Info-> bmiheader. biplanes = 1; Info-> bmiheader. bibitcount = 16; Info-> bmiheader. bicompression = bi_bitfields; Info-> bmiheader. bisizeimage = size; Info-> RGB [0] = 0xf800; Info-> RGB [1] = 0x07e0; Info-> RGB [2] = 0x001f; printf ("rgb565: % dbit, % d * % d, % d \ n ", info-> bmihead Er. bibitcount, W, H, head-> bfsize);} return size;} static int save_bmp _rgb565 (File * hfile, int W, int H, void * pdata) {int success = 0; int size = 0; bmpheader head; bitmapinfo Info; size = get_rgb565_header (W, H, & head, & info); If (size> 0) {fwrite (head. bftype, 1, 14, hfile); fwrite (& info, 1, sizeof (Info), hfile); fwrite (pdata, 1, size, hfile); success = 1 ;} return success;} static int save_bmp _rgb888 (File * Hfile, int W, int H, void * pdata) {int success = 0; int size = 0; bmpheader head; BMP info Info; size = get_rgb888_header (W, H, & head, & info); If (size> 0) {fwrite (head. bftype, 1, 14, hfile); fwrite (& info, 1, sizeof (Info), hfile); fwrite (pdata, 1, size, hfile); success = 1 ;} return success;} int save_bmp (const char * path, int W, int H, void * pdata, int bpp) {int success = 0; file * hfile = NULL; do {If (P Ath = NULL | W <= 0 | H <= 0 | pdata = NULL) {printf ("If (Path = NULL | W <= 0 | H <= 0 | pdata = NULL) \ n"); break ;} remove (PATH); hfile = fopen (path, "WB"); If (hfile = NULL) {printf ("open (% s) failed! \ N ", PATH); break;} switch (BPP) {Case 16: Success = save_bmp _rgb565 (hfile, W, H, pdata); break; Case 24: success = save_bmp _rgb888 (hfile, W, H, pdata); break; default: printf ("error: Not support format! \ N "); success = 0; break ;}} while (0); If (hfile! = NULL) fclose (hfile); Return success ;}//-------------------------------------------------------------------

3. Running Mode:

In cygwin, ndk is used to compile the executable file, and then the generated executable file is pushed to the/data/local path of the simulator,

The modified file is executable, and screenshots can be taken directly. The images are saved to/mnt/sdcard/s.bmp.

Administrator@xxx /cygdrive/e$ cd myprj/screenshot/jni/Administrator@xxx /cygdrive/e/myprj/screenshot/jni$ ndk-buildCompile thumb  : savebmp <= savebmp.cCompile thumb  : savebmp <= screenshot.cStaticLibrary  : libsavebmp.aExecutable     : saveInstall        : save => libs/armeabi/saveAdministrator@xxx /cygdrive/e/myprj/screenshot/jni$ adb shellerror: device offlineAdministrator@xxx /cygdrive/e/myprj/screenshot/jni$ adb shell#Administrator@xxx /cygdrive/e/myprj/screenshot/jni$ adb push ../libs/armeabi/save /data/local83 KB/s (10636 bytes in 0.125s)Administrator@xxx /cygdrive/e/myprj/screenshot/jni$ adb shell# cd /data/localcd /data/local# chmod 777 savechmod 777 save# ./save./savergb565:16bit,800*480,768068# ls -l /mnt/sdcardls -l /mnt/sdcardd---rwxr-x system   sdcard_rw          2012-02-19 12:39 LOST.DIRd---rwxr-x system   sdcard_rw          2012-02-20 13:22 DCIM----rwxr-x system   sdcard_rw   768068 2012-02-20 13:22 s.bmp#

PS: The VC project in the project source code is mainly used to debug the image generation function.

========================================================== ========================================================== ==================================

Currently, 32-bit support has been added to the enhanced version, but no 32-bit devices have been tested. Some netizens have already tested the support, and 32-bit devices may see color deviations and location offsets, currently, I have no way to debug it, so I have not solved the 32-bit problem.

Some websites' tests On Xiaomi mobile phones are also a matter of Color Difference and error, but later they directly use runtime.exe C ("/system/bin/screencap-P path") in Java to Capture screenshots, or PNG format. Not every device has a screencap.

For details about the pixel format in fb0, refer

Android4.0p-ics-src/system/CORE/ADB # vi framebuffer_service.c, which lists five formats, but some devices may not be the following.

        case 1: /* RGBA_8888 */            fbinfo.bpp = 32;            fbinfo.size = w * h * 4;            fbinfo.width = w;            fbinfo.height = h;            fbinfo.red_offset = 0;            fbinfo.red_length = 8;            fbinfo.green_offset = 8;            fbinfo.green_length = 8;            fbinfo.blue_offset = 16;            fbinfo.blue_length = 8;            fbinfo.alpha_offset = 24;            fbinfo.alpha_length = 8;            break;        case 2: /* RGBX_8888 */            fbinfo.bpp = 32;            fbinfo.size = w * h * 4;            fbinfo.width = w;            fbinfo.height = h;            fbinfo.red_offset = 0;            fbinfo.red_length = 8;            fbinfo.green_offset = 8;            fbinfo.green_length = 8;            fbinfo.blue_offset = 16;            fbinfo.blue_length = 8;            fbinfo.alpha_offset = 24;            fbinfo.alpha_length = 0;            break;        case 3: /* RGB_888 */            fbinfo.bpp = 24;            fbinfo.size = w * h * 3;            fbinfo.width = w;            fbinfo.height = h;            fbinfo.red_offset = 0;            fbinfo.red_length = 8;            fbinfo.green_offset = 8;            fbinfo.green_length = 8;            fbinfo.blue_offset = 16;            fbinfo.blue_length = 8;            fbinfo.alpha_offset = 24;            fbinfo.alpha_length = 0;            break;        case 4: /* RGB_565 */            fbinfo.bpp = 16;            fbinfo.size = w * h * 2;            fbinfo.width = w;            fbinfo.height = h;            fbinfo.red_offset = 11;            fbinfo.red_length = 5;            fbinfo.green_offset = 5;            fbinfo.green_length = 6;            fbinfo.blue_offset = 0;            fbinfo.blue_length = 5;            fbinfo.alpha_offset = 0;            fbinfo.alpha_length = 0;            break;        case 5: /* BGRA_8888 */            fbinfo.bpp = 32;            fbinfo.size = w * h * 4;            fbinfo.width = w;            fbinfo.height = h;            fbinfo.red_offset = 16;            fbinfo.red_length = 8;            fbinfo.green_offset = 8;            fbinfo.green_length = 8;            fbinfo.blue_offset = 0;            fbinfo.blue_length = 8;            fbinfo.alpha_offset = 24;            fbinfo.alpha_length = 8;           break;

In addition, you can refer to the source code of screenshots in android4.0 using two programs. Both of them can be screenshots, one implemented by C ++ and the other implemented by C.

ICS-Src \ frameworks \ base \ cmds \ screencap. cpp

ICS-Src \ frameworks \ base \ cmds \ screenshot. c

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.