linux下实现对framebuffer(/dev/fb0)的截屏操作

本文介绍了一款用于嵌入式系统的LCD截屏工具,该工具能够将显示屏的内容保存为BMP格式,并详细介绍了BMP文件的结构及实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在linux系统中,使用framebuffer来提供用户态进程直接操作显示屏的功能.

在嵌入式系统开发中,需要对显示屏的内容进行截取,实现一个lcd截屏工具实现对显示屏内容的截取,存储为bmp格式.

一个bmp文件有四部分组成:


其中位图文件头内容如下:

    WORD    bfType; 
    DWORD   bfSize; 
    WORD    bfReserved1; 
    WORD    bfReserved2; 
    DWORD   bfOffBits; 
bfType 说明文件的类型,该值必需是0x4D42,也就是字符'BM',否则表示根本不是BMP
bfSize 说明该位图文件的大小,用字节为单位
bfReserved1 保留,必须设置为0
bfReserved2 保留,必须设置为0
bfOffBits 说明从文件头开始到实际的图象数据之间的字节的偏移量。这个参数是非常有用的,因为位图信息头和调色板的长度会根据不同情况而变化,所以你可以用这个偏移值迅速的从文件中读取到位数据。
位图信息段内容如下:

    DWORD  biSize; 
    LONG   biWidth; 
    LONG   biHeight; 
    WORD   biPlanes; 
    WORD   biBitCount 
    DWORD  biCompression; 
    DWORD  biSizeImage; 
    LONG   biXPelsPerMeter; 
    LONG   biYPelsPerMeter; 
    DWORD  biClrUsed; 
    DWORD  biClrImportant; 
biSize 说明BITMAPINFOHEADER结构所需要的字节数
biWidth 说明图象的宽度,以象素为单位
biHeight 说明图象的高度,以象素为单位。注:这个值除了用于描述图像的高度之外,它还有另一个用处,就是指明该图像是倒向的位图,还是正向的位图。如果该值是一个正数,说明图像是倒向的,即:数据的第一行其实是图像的最后一行,如果该值是一个负数,则说明图像是正向的。大多数的BMP文件都是倒向的位图,也就是时,高度值是一个正数。
biPlanes 表示bmp图片的平面属,显然显示器只有一个平面,所以恒等于1
biBitCount 说明比特数/象素,其值为1、4、8、16、24、或32。
biCompression 说明图象数据压缩的类型,其中: 

BI_RGB:没有压缩

BI_RLE8:每个象素8比特的RLE压缩编码,压缩格式由2字节组成(重复象素计数和颜色索引);

BI_RLE4:每个象素4比特的RLE压缩编码,压缩格式由2字节组成

BI_BITFIELDS:每个象素的比特由指定的掩码决定。

BI_JPEG:JPEG格式

biSizeImage 说明图象的大小,以字节为单位。当用BI_RGB格式时,可设置为0。
biXPelsPerMeter 说明水平分辨率,用象素/米表示。
biYPelsPerMeter 说明垂直分辨率,用象素/米表示。
biClrUsed 说明位图实际使用的彩色表中的颜色索引数(设为0的话,则说明使用所有调色板项)。
biClrImportant 说明对图象显示有重要影响的颜色索引的数目,如果是0,表示都重要。

由于当前嵌入式设备使用的显示接口为RGB565格式,选择biBitCount为16的格式来存储显示屏数据.显示屏大小为800x600.

实现代码如下:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/soundcard.h>
#include <stdio.h>
#include <unistd.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>

static unsigned char sg_BHeader[] = {
    0x42, 0x4D, 0x36, 0x58, 0x02, 0x00, 0x00, 0x00,  0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00, 
    0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xF0, 0x00,  0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
#define RGB565TO1555(rgb) ((unsigned short)((unsigned short)(rgb & 0x001f) | ((unsigned short)(rgb & 0xffc0) >> 1)))
void SaveBMPFile(unsigned char *raw, char *filename)
{
    unsigned short *p = (unsigned short *)raw;
    typedef unsigned int UINT;
    typedef unsigned char UCHAR;
    UINT m_Width = 800, m_Height = 480;
    UINT i, j;
    int bmp = open(filename, O_WRONLY | O_CREAT);
    if(bmp < 0)
        return;
    sg_BHeader[0x02] = (UCHAR)(m_Width * m_Height * 2 + 0x36) & 0xff;
    sg_BHeader[0x03] = (UCHAR)((m_Width * m_Height * 2 + 0x36) >> 8) & 0xff;
    sg_BHeader[0x04] = (UCHAR)((m_Width * m_Height * 2 + 0x36) >> 16) & 0xff;
    sg_BHeader[0x05] = (UCHAR)((m_Width * m_Height * 2 + 0x36) >> 24) & 0xff;
    sg_BHeader[0x12] = (UCHAR)m_Width & 0xff;
    sg_BHeader[0x13] = (UCHAR)(m_Width >> 8) & 0xff;
    sg_BHeader[0x14] = (UCHAR)(m_Width >> 16) & 0xff;
    sg_BHeader[0x15] = (UCHAR)(m_Width >> 24) & 0xff;
    sg_BHeader[0x16] = (UCHAR)m_Height & 0xff;
    sg_BHeader[0x17] = (UCHAR)(m_Height >> 8) & 0xff;
    sg_BHeader[0x18] = (UCHAR)(m_Height >> 16) & 0xff;
    sg_BHeader[0x19] = (UCHAR)(m_Height >> 24) & 0xff;
    write(bmp, sg_BHeader, sizeof(sg_BHeader));
    for(i = 0; i < m_Height; i++)
    {
        unsigned short *c = p + (m_Height - 1 - i) * m_Width;
        unsigned short cc;
        for(j = 0; j < m_Width; j++)
        {
            cc = RGB565TO1555(*(c + j));
//            cc = *(c + j);
            write(bmp, &cc, 2);
        }
    }
    close(bmp);
}
int main(int argc, char *argv[])
{
    unsigned char buf[800*480*2];
    char *filename;
    int fb;

    
    fb = open("/dev/fb0", O_RDONLY);
    if(fb < 0)
        exit(1);
    if(argc == 2)
        filename = argv[1];
    else
        exit(1);
    printf("reading screen...\n");
    read(fb, buf, 800*480*2);
    close(fb);
    printf("saving screen...\n");
    SaveBMPFile(buf, filename);
    printf("file %s created successfully\n", filename);
    exit(0);
}
<think>嗯,用户想在Linux平台上将ARGB8888编码的原始数据从帧缓冲设备/dev/fb0转换为PNG图像。我需要先理清楚整个转换的步骤和可能用到的工具。 首先,用户提到了ARGB8888格式,这意味着每个像素用32位表示,其中A是alpha通道,接下来是红、绿、蓝各8位。不过帧缓冲设备的具体像素格式可能因硬件而异,可能需要先确认fb0的实际像素排列,比如是否真的是ARGB还是可能有其他顺序,比如BGRA或者RGBA。这时候可能需要查看framebuffer的信息,比如使用fbset命令或者读取/sys/class/graphics/fb0/modes文件来获取分辨率、位深等信息。 然后,从/dev/fb0读取原始数据。这可以通过dd命令或者编程方式读取。需要注意的是,读取的数据可能需要处理字节序的问题,尤其是如果应用程序运行在不同架构的CPU上,大端和小端可能会有影响。另外,帧缓冲设备可能需要root权限,所以用户可能需要使用sudo来执行相关命令。 接下来是处理ARGB8888数据。PNG通常支持RGBA格式,所以需要将ARGB8888转换为RGBA8888。可能需要重新排列字节顺序,或者处理alpha通道的位置。例如,ARGB在内存中的排列可能是每个像素四个字节,依次是A、R、G、B,而转换为RGBA的话,需要将顺序调整为R、G、B、A。这时候可能需要使用图像处理库,比如ImageMagick的convert工具,或者编写脚本进行转换。 另外,使用ffmpeg也是一个选项,因为它可以处理各种像素格式,并且直接生成PNG文件。用户需要指定输入的分辨率、像素格式,以及输出格式。例如,ffmpeg -f rawvideo -pix_fmt argb -s 1920x1080 -i input.raw -frames:v 1 output.png。不过需要注意,ffmpeg支持的像素格式名称是否正确,比如argb是否是有效的,可能需要查阅文档确认。 还有,用户可能没有安装这些工具,需要指导他们安装ImageMagick或ffmpeg。此外,如果原始数据中包含alpha通道,而用户不需要,可能还需要在转换时忽略alpha,或者调整透明度。 总结一下步骤应该是:1. 获取帧缓冲的参数;2. 读取原始数据;3. 转换像素格式;4. 保存为PNG。可能需要用到的工具有dd、fbset、ImageMagick、ffmpeg或者Python的PIL库。 还要考虑用户可能遇到的常见问题,比如权限问题,路径是否正确,像素格式不匹配导致颜色错误等。可能需要建议用户先尝试小尺寸的截图,比如用dd读取部分数据测试,避免处理大文件时的耗时。 最后,可能需要给出具体的命令行示例,让用户可以直接复制粘贴,比如使用dd命令读取fb0,然后用convert命令处理,或者用Python脚本读取并转换。同时提醒用户替换命令中的分辨率参数为实际值,否则生成的图片尺寸不对会导致转换失败。</think>在Linux系统中将帧缓冲设备$(\text{/dev/fb0})$中的ARGB8888原始数据转换为PNG图像,可通过以下步骤实现: ### 一、获取帧缓冲参数 首先需要确定分辨率、像素格式等关键参数: ```bash # 查看当前帧缓冲设备信息 cat /sys/class/graphics/fb0/virtual_size cat /sys/class/graphics/fb0/bits_per_pixel ``` 典型输出示例:$1920\times1080$分辨率,32位色深(对应ARGB8888)[^2] ### 二、读取原始数据 使用`dd`命令捕获帧缓冲内容: ```bash sudo dd if=/dev/fb0 of=./framebuffer.raw bs=1 count=$((1920*1080*4)) ``` 此处$1920\times1080\times4$对应分辨率与ARGB8888的4字节/像素 ### 三、格式转换方法 #### 方法1:使用ImageMagick ```bash convert -size 1920x1080 -depth 8 \ rgba:./framebuffer.raw -channel rgba -separate \ -swap 0,1 -swap 1,2 -swap 2,3 -combine output.png ``` 需注意通道顺序调整(ARGB→RGBA) #### 方法2:使用ffmpeg ```bash ffmpeg -f rawvideo -pix_fmt argb -s 1920x1080 -i framebuffer.raw \ -vf "format=rgba" output.png ``` #### 方法3:Python脚本(需PIL库) ```python from PIL import Image import numpy as np width, height = 1920, 1080 with open("framebuffer.raw", "rb") as f: data = np.frombuffer(f.read(), dtype=np.uint8).reshape((height, width, 4)) Image.fromarray(data[..., 1:], 'RGB').save('output.png') # 丢弃Alpha通道 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值