1. 程式人生 > >FrameBuffer中獲取Android螢幕截圖

FrameBuffer中獲取Android螢幕截圖

引子 我們知道,DDMS可以很容易的獲取Android 手機 的螢幕截圖,那麼它是怎麼做到的呢?  其實,android手機上有一個叫做FrameBuffer的裝置,影象資訊都是通過FrameBuffer寫到手機螢幕上去的。因此可以通過讀取此裝置中的資料來獲取當前正在顯示的影象。當然DDMS也是這麼做到的。 FrameBuffer 對應的裝置檔案就是/dev/graphics/fb0。因此我們可以通過下面的程式碼讀取螢幕影象資料。其中傳入的引數fd為一個檔案描述符,也可以是 socket描述符。這樣我們就可以把從fb中讀取的螢幕影象資訊傳遞給我們自己的應用,從而獲取手機螢幕資訊。  
void framebuffer_service(int fd)
{
    struct fb_var_screeninfo vinfo;
    int fb, offset;
    char x[256];
 
    struct fbinfo fbinfo;
    unsigned i, bytespp;
 
    fb = open("/dev/graphics/fb0", O_RDONLY);
    if(fb < 0) goto done;
 
    if(ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) < 0) goto done;
    fcntl(fb, F_SETFD, FD_CLOEXEC);
 
    bytespp = vinfo.bits_per_pixel / 8;
 
    fbinfo.version = DDMS_RAWIMAGE_VERSION;
    fbinfo.bpp = vinfo.bits_per_pixel;
    fbinfo.size = vinfo.xres * vinfo.yres * bytespp;
    fbinfo.width = vinfo.xres;
    fbinfo.height = vinfo.yres;
    fbinfo.red_offset = vinfo.red.offset;
    fbinfo.red_length = vinfo.red.length;
    fbinfo.green_offset = vinfo.green.offset;
    fbinfo.green_length = vinfo.green.length;
    fbinfo.blue_offset = vinfo.blue.offset;
    fbinfo.blue_length = vinfo.blue.length;
    fbinfo.alpha_offset = vinfo.transp.offset;
    fbinfo.alpha_length = vinfo.transp.length;
 
    /* 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 = vinfo.xoffset * bytespp;
 
    offset += vinfo.xres * vinfo.yoffset * bytespp;
    printf("offset %d/n", offset);
 
    if(writex(fd, &fbinfo, sizeof(fbinfo))) goto done;
 
    lseek(fb, offset, SEEK_SET);
    for(i = 0; i < fbinfo.size; i += 256) {
      if(readx(fb, &x, 256)) goto done;
      if(writex(fd, &x, 256)) goto done;
    }
 
    if(readx(fb, &x, fbinfo.size % 256)) goto done;
    if(writex(fd, &x, fbinfo.size % 256)) goto done;
 
done:
    if(fb >= 0) close(fb);
    close(fd);
}
(evilcode)