android fb 截屏轻量级版本

应用里面读取fb0需要先修改fb0的权限,在root过的手机可以通过chmod 777 /dev/graphics/fb0 修改。

以下是读取屏幕内容并保存为一个bmp图像的实现。

 

#include <stdio.h>
#include <stdlib.h>
#include <linux/fb.h>

int save_bmp(const char * path, int w, int h, void * pdata, int bpp);

#define NO_ERROR 1
#define PROT_READ  0x1
#define PROT_WRITE 0x2
#define PROT_EXEC  0x4
#define PROT_NONE  0x0

#define MAP_SHARED    0x01
#define MAP_PRIVATE   0x02
#define MAP_FIXED     0x10
#define MAP_ANONYMOUS 0x20
#define MAP_FAILED (void*)-1


static int vinfoToPixelFormat(int bits_per_pixel,int* bytespp, int* f)
{

    switch (bits_per_pixel) {
        case 16:
            *f = 4;//PIXEL_FORMAT_RGB_565;
            *bytespp = 2;
   ms_message("--dxp--pixelformat is PIXEL_FORMAT_RGB_565");
            break;
        case 24:
            *f = 3;//PIXEL_FORMAT_RGB_888;
            *bytespp = 3;
   ms_message("--dxp--pixelformat is PIXEL_FORMAT_RGB_888");
            break;
        case 32:
            // TODO: do better decoding of vinfo here
            *f = 5;//PIXEL_FORMAT_RGBX_8888;
            *bytespp = 4;
   ms_message("--dxp--pixelformat is PIXEL_FORMAT_RGBX_8888");
            break;
        default:
            return -1;
    }
    return NO_ERROR;
}

 

int fb_capture(int * fbw,int * fbh)
{
 int mapsize = 0;
 void const* mapbase = MAP_FAILED;
 void const * base=0;
 int w,h,s,f,size;
    const char* fbpath = "/dev/graphics/fb0";
    int fb = open(fbpath, O_RDONLY);
    if (fb >= 0) {
        struct fb_var_screeninfo vinfo;
        if (ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) == 0) {
            uint32_t bytespp;
            if (vinfoToPixelFormat(vinfo.bits_per_pixel, &bytespp, &f) == NO_ERROR) {
                size_t offset = (vinfo.xoffset + vinfo.yoffset*vinfo.xres) * bytespp;
                w = vinfo.xres;
                h = vinfo.yres;
                s = vinfo.xres;
                size = w*h*bytespp;
                mapsize = offset + size;
                mapbase = mmap(0, mapsize, PROT_READ, MAP_SHARED, fb, 0);
                if (mapbase != MAP_FAILED) {
                     base = (void const *)((char const *)mapbase + offset);
                    *fbw = w;
                     *fbh = h;
                 }
                 save_bmp("/storage/sdcard0/test.bmp", w, h, base, vinfo.bits_per_pixel);
                  munmap((void *)mapbase, mapsize);
            }
        }
  
        close(fb);
        return 0;
    }else{
        printf("getframebuffer fail !");
        return -1;
 }
}

//-------------------------------------------------------------------
/*
  位图文件的组成
  结构名称 符 号
  位图文件头 (bitmap-file header) BITMAPFILEHEADER bmfh
  位图信息头 (bitmap-information header) BITMAPINFOHEADER bmih
  彩色表 (color table) RGBQUAD aColors[]
  图象数据阵列字节 BYTE aBitmapBits[]
*/
typedef struct bmp_header
{
 short twobyte   ;//两个字节,用来保证下面成员紧凑排列,这两个字符不能写到文件中
 //14B
 char bfType[2]   ;//!文件的类型,该值必需是0x4D42,也就是字符'BM'
 unsigned int bfSize  ;//!说明文件的大小,用字节为单位
 unsigned int bfReserved1;//保留,必须设置为0
 unsigned int bfOffBits ;//!说明从文件头开始到实际的图象数据之间的字节的偏移量,这里为14B+sizeof()
}BMPHEADER;

typedef struct bmp_info
{
 //40B
 unsigned int biSize   ;//!BMPINFO结构所需要的字数
 int biWidth     ;//!图象的宽度,以象素为单位
 int biHeight    ;//!图象的宽度,以象素为单位,如果该值是正数,说明图像是倒向的,如果该值是负数,则是正向的
 unsigned short biPlanes  ;//!目标设备说明位面数,其值将总是被设为1
 unsigned short biBitCount ;//!比特数/象素,其值为1、4、8、16、24、或32
 unsigned int biCompression ;//说明图象数据压缩的类型
#define BI_RGB        0L //没有压缩
#define BI_RLE8       1L //每个象素8比特的RLE压缩编码,压缩格式由2字节组成(重复象素计数和颜色索引);
#define BI_RLE4       2L //每个象素4比特的RLE压缩编码,压缩格式由2字节组成
#define BI_BITFIELDS  3L //每个象素的比特由指定的掩码决定。
 unsigned int biSizeImage ;//图象的大小,以字节为单位。当用BI_RGB格式时,可设置为0
 int biXPelsPerMeter   ;//水平分辨率,用象素/米表示
 int biYPelsPerMeter   ;//垂直分辨率,用象素/米表示
 unsigned int biClrUsed  ;//位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)
 unsigned int biClrImportant ;//对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。
}BMPINFO;

typedef struct tagRGBQUAD {
 unsigned char rgbBlue;
 unsigned char rgbGreen;
 unsigned char rgbRed;
 unsigned char rgbReserved;
} RGBQUAD;

typedef struct tagBITMAPINFO {
    BMPINFO    bmiHeader;
    //RGBQUAD    bmiColors[1];
 unsigned int rgb[3];
} BITMAPINFO;

static int get_rgb888_header(int w, int h, BMPHEADER * head, BMPINFO * 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;
  size = head->bfSize - head->bfOffBits;
  
  info->biSize = sizeof(BMPINFO);
  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->bmiHeader.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;
 BMPINFO 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;
}

static int save_bmp_rgb8888(FILE * hfile, int w, int h, void * pdata)
{
 int success = 0;
 int size = 0;
 BMPHEADER head;
 BMPINFO info;
 int i=0;
 unsigned char * sdata = pdata;
 
 size = get_rgb888_header(w, h, &head, &info);
 if (size > 0) {
  fwrite(head.bfType, 1, 14, hfile);
  fwrite(&info, 1, sizeof(info), hfile);
  for(i=0;i<w*h;i++){
   fwrite(sdata+i*4, 1, 3, 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 (path == 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;
  case 32:
   success = save_bmp_rgb8888(hfile, w, h, pdata);
   break;
  default:
   ms_message("error: not support format!\n");
   success = 0;
   break;
  }
 } while (0);

 if (hfile != NULL)
  fclose(hfile);
 
 return success;
}

//-------------------------------------------------------------------

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值