framebuffer 截屏功能,并保存为 24位bmp图片

背景:用framebuffer 去实现截屏功能,并想将图片保存位24位深的bmp图片

网上关于截屏的代码解析挺多的,这里不做太多的描述

framebuffer 直接保存bmp 图片是 32 位的,需要进行转化

注意一下,如何将图片保存为24位bmp 图片即可

直接上源码

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <linux/fb.h>
#include <linux/ioctl.h>
#include <sys/ioctl.h>

// 保存BMP图像所需的Header结构
#pragma pack(push,2)
typedef struct BitmapFileHeader_s
{
    unsigned short    bfType;
    unsigned int    bfSize;
    unsigned short    bfReserved1;
    unsigned short   bfReserved2;
    unsigned int   bfOffBits;
} BitmapFileHeader;
#pragma pack(pop)
 
typedef struct BitmapInfoHeader_s{
    unsigned int     biSize;
    unsigned int      biWidth;
    unsigned int      biHeight;
    unsigned short      biPlanes;
    unsigned short      biBitCount;
    unsigned int     biCompression;
    unsigned int     biSizeImage;
    unsigned int      biXPelsPerMeter;
    unsigned int      biYPelsPerMeter;
    unsigned int     biClrUsed;
    unsigned int     biClrImportant;
} BitmapInfoHeader;


void screenshot()
{
    int i = 0;
    int fbfd = 0;
    int fd = 0;
    char* fbp = NULL;
    char* fp = NULL;
    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;
    long int linesize = 0;
    long int screensize = 0;
    long int fsize = 0;
    BitmapFileHeader* fileHeader = NULL;
    BitmapInfoHeader* infoHeader = NULL;
    /*打开设备文件*/
    fbfd = open("/dev/fb0", O_RDONLY);
    /*取得屏幕相关参数*/
    ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo);
    ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo);
    /*计算屏幕缓冲区大小*/
    linesize = vinfo.xres * vinfo.bits_per_pixel / 8;
    screensize = linesize * vinfo.yres;
    /*映射屏幕缓冲区到用户地址空间*/
    fbp=(char*)mmap(0,screensize,PROT_READ,MAP_SHARED, fbfd, 0);
 
    fd = open("screenshot.bmp", O_CREAT|O_RDWR);
    /*计算BMP文件大小*/
    fsize = screensize + sizeof(BitmapFileHeader) + sizeof(BitmapInfoHeader);
    /*调整BMP文件大小,避免mmap之后写内存时出现SIGBUS*/
    ftruncate(fd, fsize);
    fp = (char*)mmap(0,fsize,PROT_READ|PROT_WRITE,MAP_SHARED, fd, 0);
 
    /*设置BMP图像信息*/
    fileHeader = (BitmapFileHeader*)fp;
    infoHeader = (BitmapInfoHeader*)(fp + sizeof(BitmapFileHeader));
    fileHeader->bfOffBits = fsize-screensize;
    fileHeader->bfSize = fsize;
    fileHeader->bfType = 0x4d42;
    infoHeader->biHeight = vinfo.yres;
    infoHeader->biWidth = vinfo.xres;
    infoHeader->biPlanes = 1;
    infoHeader->biBitCount = 24; // 修改为24位深度
    infoHeader->biSizeImage = screensize;
    infoHeader->biSize = sizeof(BitmapInfoHeader);
 
    /*逐行拷贝图像,反转行顺序,并将32位颜色转换为24位颜色*/
    for (i = 0; i < vinfo.yres; ++i)
    {
        char* src = fbp + (vinfo.yres - i - 1) * linesize;
        char* dest = fp + (fsize - screensize) + i * (vinfo.xres * 3);

        int j;
        for (j = 0; j < vinfo.xres; ++j)
        {
            /*从32位颜色中提取RGB分量,并将其写入24位深度的目标图像中*/
            unsigned int color = *((unsigned int*)src);
            unsigned char blue = (color >> 0) & 0xFF;
            unsigned char green = (color >> 8) & 0xFF;
            unsigned char red = (color >> 16) & 0xFF;

            *dest = blue;
            *(dest + 1) = green;
            *(dest + 2) = red;

            src += 4;
            dest += 3;
        }
    }

    munmap(fp, fsize);
    close(fd);
 
    /*释放缓冲区,关闭设备*/
    munmap(fbp, screensize);
    close(fbfd);
}

int main()
{
    screenshot();
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值