在android上面做屏幕截图需要经过两个步骤
1.从framebuffer获取RGB的原始字节(大小是 宽*高*图像深度/8)
int fbfd = 0;
struct fb_var_screeninfo vinfo;//保存这framebuffer的各自数据,宽高等等
fbfd = open("/dev/graphics/fb0", O_RDWR);
if (!fbfd) {
printf("Error: cannot open framebuffer device.\n");
return 0;
}
if (ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo)) {
printf("Error: reading variable information.\n");
return 0;
}
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel >> 3;
fbp = (char *) mmap(0, screensize, PROT_READ, MAP_SHARED, fbfd, 0);
uint8_t rgv_24[screensize];
memcpy(rgv_24, fbp, screensize);
这样rgv_24中就是我们得到的RGB原始字节了,接下来的就是执行第儿个步骤了
2.将原始字节转成JPEG或者PNG等等压缩后的可以直接看的图
第一种方法:
在RGB原始字节的最前面加上BMP位图的54个描述字节,即可成一张完成的BMP位图
第二种方法:
将RGB原始字节数据回传到java中使用Bitmap转换成图片
第三种方法就是在C中直接调用Android SkImageEncoder等接口转成图片,不过要注意的是在SkBitMap中不支持RGB24的位图,因此需要转换成RGB565才能往下走。
SkBitmap mSkBitmap;
mSkBitmap.setConfig(SkBitmap::kRGB_565_Config, vinfo.xres, vinfo.yres);
mSkBitmap.setPixels(rgv_16);
SkDynamicMemoryWStream stream;//图片流,其实就是图片内容
SkImageEncoder::EncodeStream(&stream, mSkBitmap, SkImageEncoder::kJPEG_Type,100);
int fd = open(ssPath, O_WRONLY | O_CREAT); //打开文件
int size = stream.getOffset();//这个是图片的大小
write(fd, stream.getStream(), size);//保存到图片
close(fd);
附:
static void rgb24_to_rgb565(long rgb24_size, uint8_t *rgb24, uint8_t *rgb16) {
int i = 0, j = 0;
for (i = 0; i < rgb24_size; i += 3) {
rgb16[j] = rgb24[i] >> 3; // B
rgb16[j] |= ((rgb24[i + 1] & 0x1C) << 3); // G
rgb16[j + 1] = rgb24[i + 2] & 0xF8; // R
rgb16[j + 1] |= (rgb24[i + 1] >> 5); // G
j += 2;
}
}