Android上使用SkBitmap 进行屏幕截图

时间:2021-09-13 15:21:24

在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;

                }

        }