这里啥也没有哦!🍺;|

feige_c

园龄:2年8个月粉丝:3关注:0

fb应用程序

一.什么是Frame Buffer

​ 所以在 Linux 系统中,显示设备被称为 Frame Buffer 设备帧缓冲设备).

二.LCD 的基础知识

LCD Framebuffer 就是一块显存,在嵌入式系统中,显存是被包含在内存中。LCD Framebuffer里的若干字节(根据驱动程序对LCD控制器的配置而定)表示LCD屏幕中的一个像素点,一一对应整个LCD屏幕。举个例子,LCD屏幕是800*600的分辨率,即LCD屏幕存在480000个像素点,若每个像素点4个字节表示,那么LCD Framebuffer显存大小为480000 *4=960000字节,即1.92MB。因此我们的内存将会分割至少1.92MB的空间用作显存。具体地址在哪里,这个就是又驱动程序去定,应用程序只需直接使用即可,硬件相关操作已由驱动程序封装好。

Framebuffer原理

如上图,我们只需要往Framebuffer中填入不同的值,驱动程序和硬件控制器就会把这些数据传输到对应LCD屏幕上的像素点,从而显示不同的颜色。由此可知,我们应用程序只需要针对Framebuffer操作即可,其他交给驱动程序和硬件。

三.LCD 应用编程介绍

在应用程序中,操作/dev/fbX 的一般步骤如下:
①、首先打开/dev/fbX 设备文件。
②、 使用 ioctl()函数获取到当前显示设备的参数信息,譬如屏幕的分辨率大小、像素格式,根据屏幕参数计算显示缓冲区的大小。
③、通过存储映射 I/O 方式将屏幕的显示缓冲区映射到用户空间(mmap)。
④、映射成功后就可以直接读写屏幕的显示缓冲区,进行绘图或图片显示等操作了。
⑤、完成显示后, 调用 munmap()取消映射、并调用 close()关闭设备文件。

使用 ioctl()获取屏幕参数信息

​ 当打开 LCD 设备文件之后,需要先获取到 LCD 屏幕的参数信息,譬如 LCD 的 X 轴分辨率、 Y 轴分辨率以及像素格式等信息,通过这些参数计算出 LCD 显示缓冲区的大小。
​ 通 过 ioctl() 函 数 来 获 取 屏 幕 参 数 信 息 , 对 于 Framebuffer 设 备 来 说 , 常 用 的 request 包 括FBIOGET_VSCREENINFO、 FBIOPUT_VSCREENINFO、 FBIOGET_FSCREENINFO。

  • FBIOGET_VSCREENINFO

    获取 FrameBuffer 设备的可变参数信息,可变参数信息使用 struct fb_var_screeninfo 结 构 体 来 描 述 , 所 以 此 时 ioctl() 需 要 有第 三 个 参 数 , 它 是 一 个 struct fb_var_screeninfo *指针,指向 struct fb_var_screeninfo 类型对象, 调用 ioctl()会将 LCD 屏的可变参数信息保存在 struct fb_var_screeninfo 类型对象中,

    struct fb_var_screeninfo fb_var; //描述可变参数信息
    ioctl(fd, FBIOGET_VSCREENINFO, &fb_var); //将信息保存在fb_var对象中
    
  • FBIOPUT_VSCREENINFO

    表示设置 FrameBuffer 设备的可变参数信息,既然是可变参数,那说明应用层可对其进行修改、重新配置,当然前提条件是底层驱动支持这些参数的动态调整,譬如在我们的 Windows 系统中,用户可以修改屏幕的显示分辨率,这就是一种动态调整。同样此时 ioctl()需要有第三个参数, 也是一个 struct fb_var_screeninfo *指针,指向 struct fb_var_screeninfo 类型对象, 表示用 struct fb_var_screeninfo 对象中填充的数据设置 LCD,

    struct fb_var_screeninfo fb_var = {0}; //创建对象
    /* 对 fb_var 进行数据填充 */ //初始化对象
    ......
    /* 设置可变参数信息 */
    ioctl(fd, FBIOPUT_VSCREENINFO, &fb_var);
    
  • FBIOGET_FSCREENINFO

    表示获取 FrameBuffer 设备的固定参数信息,既然是固定参数,那就意味着应用程序不可修改。固定参数信息使用struct fb_fix_screeninfo结构体来描述,所以此时ioctl()需要有第三个参数,它是一个 struct fb_fix_screeninfo *指针,指向 struct fb_fix_screeninfo 类型对象,调用 ioctl()会将 LCD 的固定参数信息保存在 struct fb_fix_screeninfo 对象中,如下所示:

    struct fb_fix_screeninfo fb_fix;
    ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix);
    

相关宏

上面提到的三个宏和两个结构体都定义再<linux/fb.h>头文件中

#define FBIOGET_VSCREENINFO 0x4600 //获取可变参数
#define FBIOPUT_VSCREENINFO 0x4601 //设置可变参数
#define FBIOGET_FSCREENINFO 0x4602 //获取固定参数

相关结构体

struct fb_var_screeninfo 结构体

xresyres可以获取分辨率 bpp表示像素深度:每一个像素点用多少个 bit 位来描述颜色 xres * yres * bits_per_pixel / 8 就是一块显存大小

red、 green、 blue 描述了 RGB 颜色值中 R、 G、 B 三种颜色通道分别使用多少 bit 来表示以及它们各自的偏移量,通过 red、 green、 blue 变量可知道 LCD 的 RGB 像素格式,譬如是 RGB888 还是 RGB565,亦或者是 BGR888、 BGR565 等。

struct fb_var_screeninfo {
__u32 xres; /* 可视区域,一行有多少个像素点, X 分辨率 */
__u32 yres; /* 可视区域,一列有多少个像素点, Y 分辨率 */
__u32 xres_virtual; /* 虚拟区域,一行有多少个像素点 */
__u32 yres_virtual; /* 虚拟区域,一列有多少个像素点 */
__u32 xoffset; /* 虚拟到可见屏幕之间的行偏移 */
__u32 yoffset; /* 虚拟到可见屏幕之间的列偏移 */
__u32 bits_per_pixel; /* 每个像素点使用多少个 bit 来描述,也就是像素深度 bpp */
__u32 grayscale; /* =0 表示彩色, =1 表示灰度, >1 表示 FOURCC 颜色 */
/* 用于描述 R、 G、 B 三种颜色分量分别用多少位来表示以及它们各自的偏移量 */
struct fb_bitfield red; /* Red 颜色分量色域偏移 */
struct fb_bitfield green; /* Green 颜色分量色域偏移 */
struct fb_bitfield blue; /* Blue 颜色分量色域偏移 */
struct fb_bitfield transp; /* 透明度分量色域偏移 */
__u32 nonstd; /* nonstd 等于 0,表示标准像素格式;不等于 0 则表示非标准像素格式 */
__u32 activate;
__u32 height; /* 用来描述 LCD 屏显示图像的高度(以毫米为单位) */
__u32 width; /* 用来描述 LCD 屏显示图像的宽度(以毫米为单位) */
__u32 accel_flags;
/* 以下这些变量表示时序参数 */
__u32 pixclock; /* pixel clock in ps (pico seconds) */
__u32 left_margin; /* time from sync to picture */
__u32 right_margin; /* time from picture to sync */
__u32 upper_margin; /* time from sync to picture */
__u32 lower_margin;
__u32 hsync_len; /* length of horizontal sync */
__u32 vsync_len; /* length of vertical sync */
__u32 sync; /* see FB_SYNC_* */
__u32 vmode; /* see FB_VMODE_* */
__u32 rotate; /* angle we rotate counter clockwise */
__u32 colorspace; /* colorspace for FOURCC-based modes */
__u32 reserved[4]; /* Reserved for future compatibility */
};
/***********************************************************/
struct fb_bitfield {
__u32 offset; /* 偏移量 */
__u32 length; /* 长度 */
__u32 msb_right; /* != 0 : Most significant bit is right */
};

struct fb_fix_screeninfo 结构体

smem_start 表示显存的起始地址,这是一个物理地址. smem_len 表示显存的长度,这个长度并一定等于 LCD 实际的显存大小。 line_length 表示屏幕的一行像素点有多少个字节,通常可以使用 line_length * yres 来得到屏幕显示缓冲区的大小。

struct fb_fix_screeninfo {
char id[16]; /* 字符串形式的标识符 */
unsigned long smem_start; /* 显存的起始地址(物理地址) */
__u32 smem_len; /* 显存的长度 */
__u32 type;
__u32 type_aux;
__u32 visual;
__u16 xpanstep;
__u16 ypanstep;
__u16 ywrapstep;
__u32 line_length; /* 一行的字节数 */
unsigned long mmio_start; /* Start of Memory Mapped I/O(physical address) */
__u32 mmio_len; /* Length of Memory Mapped I/O */
__u32 accel; /* Indicate to driver which specific chip/card we have */
__u16 capabilities;
__u16 reserved[2];
};

应用编程(获取屏幕信息)

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/fb.h>
int main(int argc, char  *argv[])
{
    struct fb_fix_screeninfo fb_fix;
	struct fb_var_screeninfo fb_var;
    int fd;
	/* 打开 framebuffer 设备 */
	if (0 > (fd = open("/dev/fb0", O_WRONLY))) {
		perror("open error");
		exit(-1);
	}
	/* 获取参数信息 */
	ioctl(fd, FBIOGET_VSCREENINFO, &fb_var);
	ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix);
	printf("分辨率: %d*%d\n"
		"像素深度 bpp: %d\n"
		"一行的字节数: %d\n"
		"像素格式: R<%d %d> G<%d %d> B<%d %d>\n",
		fb_var.xres, fb_var.yres, fb_var.bits_per_pixel,
		fb_fix.line_length,
		fb_var.red.offset, fb_var.red.length,
		fb_var.green.offset, fb_var.green.length,
		fb_var.blue.offset, fb_var.blue.length);
	/* 关闭设备文件退出程序 */
	close(fd);
	exit(0);
}

这里获取到的数据如下图 一共有480*854个像素点 每一个像素点用16个bit位来表示 像素格式为RGB565的

屏幕参数

四.图片格式

4.1.BMP格式

4.1.1bmp图像介绍:

一般常用的图片格式有三种:JPEG(或 JPG)、 PNG、 BMP还有动图GIF。

BMP(全称 Bitmap)是 Window 操作系统中的标准图像文件格式,文件后缀名为“.bmp”,使用非常广。它采用位映射存储格式,除了图像深度可选以外,图像数据没有进行任何压缩,因此, BMP 图像占用的空间很大,但是没有失真、 并且解析 BMP 图像简单。

BMP 文件的图像深度可选 lbit、 4bit、 8bit、 16bit、 24bit 以及 32bit,典型的 BMP 图像文件由四部分组成:

  1. BMP 文件头(BMP file header),它包含 BMP 文件的格式、大小、 位图数据的偏移量等信息;
  2. 位图信息头(bitmap information) ,它包含位图信息头大小、 图像的尺寸、 图像大小、 位平面数、压缩方式以及颜色索引等信息;
  3. 调色板(color palette),这部分是可选的,如果使用索引来表示图像, 调色板就是索引与其对应颜色的映射表;
  4. 位图数据(bitmap data),也就是图像数据。

BMP 文件头、位图信息头、调色板和位图数据, 总结如下表所示:

数据段名称 大小(Byte) 说明
bmp 文件头 (bmp file header) 14 包含 BMP 文件的格式、大小、到位图数据的 偏移量等信息
位图信息头 (bitmap information) 通常为 40 或 56 字节 包含位图信息头大小、 图像的尺寸、图像大 小、位平面数、压缩方式以及颜色索引等信息;
调色板 (color palette) 由颜色索引数决定 可选,如果使用索引来表示图像的颜色, 则调 色板就是索引与其对应颜色的映射表;
位图数据 (bitmap data) 由图像尺寸决定 图像数据

一般常见的图像都是以 16 位(RGB 565)、 24 位(RGB 888) 色图像为主,我们称这样的图像为真彩色图像, 真彩色图像是不需要调色板的,即位图信息头后面紧跟的就是位图数据了。

①bmp头文件

Windows 下为 bmp 文件头定义了如下结构体:

typedef struct tagBITMAPFILEHEADER
{
	UINT16 bfType;
	DWORD bfSize;
	UINT16 bfReserved1;
	UINT16 bfReserved2;
	DWORD bfOffBits;
} BITMAPFILEHEADER;
变量名 地址偏移 大小 作用
bfType 00H 2 bytes 说明 bmp 文件的类型,可取值为: ①BM – Windows ②BA – OS/2 Bitmap Array ③CI – OS/2 Color Icon ④CP – OS/2 Color Pointer ⑤IC – OS/2 Icon ⑥PT – OS/2 Pointer
bfSize 02H 4 bytes 说明该文件的大小,以字节为单位。
bfReserved1 06H 2 bytes 保留字段,必须设置为 0。
bfReserved2 08H 2 bytes 保留字段,必须设置为 0。
bfOffBits 0AH 4 bytes 说明从文件起始位置到图像数据之间的字节偏移量。 这个参数非常有用,因为位图信息头和调色板的长度 会根据不同的情况而变化,所以我们可以用这个偏移 量迅速从文件中找到图像数据的偏移地址

bmp文件头解析

②位图信息头

Windows 下为位图信息头定义了如下结构体:

typedef struct tagBITMAPINFOHEADER {
	DWORD biSize;
	LONG biWidth;
	LONG biHeight;
	WORD biPlanes;
	WORD biBitCount;
	DWORD biCompression;
	DWORD biSizeImage;
	LONG biXPelsPerMeter;
	LONG biYPelsPerMeter;
	DWORD biClrUsed;
	DWORD biClrImportant;
} BITMAPINFOHEADER;
变量名 地址偏移 大小 作用
biSize 0EH 4 bytes 位图信息头大小。
biWidth 12H 4 bytes 图像的宽度,以像素为单位。
biHeight 16H 4 bytes 图像的高度,以像素为单位。 注意,这个值除了用于描述图像的高度之外, 它还有另外一个用途,用于指明该图像是倒向 的位图、还是正向的位图。 如果该值是一个正数,说明是倒向的位图;如 果该值是一个负数,则说明是正向的位图。 一般情况下, BMP 图像都是倒向的位图,也就 是该值是一个正数。
biPlanes 1AH 2 bytes 色彩平面数,该值总被设置为 1。
biBitCount 1CH 2 bytes 像素深度,指明一个像素点需要多少个 bit 数据 来描述,其值可为 1、 4、 8、 16、 24、 32
biCompression 1EH 4 bytes 说明图像数据的压缩类型,取值范围如下: ①0 – RGB 方式 ②1 – 8bpp 的 RLE 方式,只用于 8bit 位图 ③2 – 4bpp 的 RLE 方式, 只用于 4bit 位图 ④3 – Bit-fields 方式 ⑤4 – 仅用于打印机 ⑥5 – 仅用于打印机
biSizeImage 22H 4 bytes 说明图像的大小,以字节为单位,当压缩类型 为 BI_RGB 时,可设置为 0。
biXPelsPerMeter 26H 4 bytes 水平分辨率,用像素/米来表示,有符号整数。
biYPelsPerMeter 2AH 4 bytes 垂直分辨率,用像素/米来表示,有符号整数。
biClrUsed 2EH 4 bytes 说明位图实际使用的彩色表中的颜色索引数。
biClrImportant 32H 4 bytes 说明对图像显示有重要影响的颜色索引的数 目,如果是 0,则表示都重要。

bmp位图信息头解析

只有压缩方式选项被设置为 bit-fileds(0x3) 时, 位图信息头的大小才会等于 56 字节,否则,为 40 字节。 56 个字节相比于 40 个字节,多出了 16 个字节, 那么多出的 16 个字节数据描述了什么信息呢? 稍后再给大家介绍。

③调色板:

调色板是单色、 16 色、 256 色位图图像文件所持有的,如果是 16 位、 24 位以及 32 位位图文件,则 BMP文件组成部分中不包含调色板,关于调色板这里不过多介绍,有兴趣可以自己去了解。

④位图数据:

位图数据其实就是图像的数据,24位位图用三个字节数据来表示一个像素点的颜色,同理16位位图用两个字节32位位图用4个字节.

BMP 位图分为正向的位图和倒向的位图,主要区别在于图像数据存储的排列方式如下如所示(左边对应的是正向位图,右边对应的则是倒向位图) :

正向位图和倒向位图

所以正向位图先存储图像的第一行数据,从左到右依次存放,接着存放第二行,依次这样;而倒向位图,则先存储图像的最后一行(倒数第一行)数据,也是从左到右依次存放,接着倒数二行,依次这样。

⑤RGB 和 Bit-Fields

当图像中引用的色彩超过 256 种时,就需要 16bpp 或更高 bpp 的位图(24 位、 32 位)。调色板不适合bpp 较大的位图,因此 16bpp 及以上的位图都不使用调色板,不使用调色板的位图图像有两种编码格式:RGB 和 Bit-Fields(下称 BF) 。

RGB 编码格式是一种均分的思想, 使 Red、 Green、 Blue 三种颜色信息容量一样大:

  1. 24bpp-RGB:在 24bits 中,低 8 位表示 Blue 分量;中 8 为表示 Green 分量;高 8 位表示 Red分量。
  2. 32bpp-RGB:低 24 位的编码方式与 24bpp 位图相同,最高 8 位用来表示透明度 Alpha 分量。对于需要半透过效果的图像,更好的选择是 PNG 格式。

BF 编码格式与 RGB 不同,它利用位域操作,人为地确定 RGB 三分量所包含的信息容量。

  1. 位图信息头中:当压缩方式选项置为 BF 时, 位图信息头大小比平时多出 16 字节, 这 16 个字节实际上是 4个 32bit 的位域掩码, 按照先后顺序,它们分别是 R、 G、 B、 A 四个分量的位域掩码, 当然如果没有 Alpha分量,则 Alpha 掩码没有实际意义。
  2. 位域掩码的作用是指出 R、 G、 B 三种颜色信息容量的大小,分别使用多少个 bit 数据来表示,以及三种颜色分量的位置偏移量。譬如对于 16 位色的 RGB565 图像,通常使用 BF 编码格式,同样这也是 BF 编码格式最著名和最普遍的应用之一, 它的 R、 G 和 B 分量的位域掩码分别是 0xF800、 0x07E0 和 0x001FR 通道使用 2 个字节中的高 5 位表示, G 通道使用 2 个字节中的中间 6 位表示。而 B 通道则使用 2个字节中的最低 5 位表示。

4.1.2在LCD上显示BMP图像

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <string.h>
#include <linux/fb.h>
#include <sys/mman.h>
/* https://blog.csdn.net/qlexcel/article/details/92656797 __attribute__的使用*/
/**** BMP文件头数据结构 ****/
typedef struct {
    unsigned char type[2];      //文件类型
    unsigned int size;          //文件大小
    unsigned short reserved1;   //保留字段1
    unsigned short reserved2;       //保留字段2
    unsigned int offset;        //到位图数据的偏移量
} __attribute__ ((packed)) bmp_file_header;

/**** 位图信息头数据结构 ****/
typedef struct {
    unsigned int size;          //位图信息头大小
    int width;                  //图像宽度
    int height;                 //图像高度
    unsigned short planes;          //位面数
    unsigned short bpp;         //像素深度 
    unsigned int compression;   //压缩方式
    unsigned int image_size;    //图像大小
    int x_pels_per_meter;       //像素/米
    int y_pels_per_meter;       //像素/米 
    unsigned int clr_used;
    unsigned int clr_omportant;
} __attribute__ ((packed)) bmp_info_header;

/**** 静态全局变量 ****/
static struct fb_fix_screeninfo fb_fix;
static struct fb_var_screeninfo fb_var;
static unsigned short *screen_base = NULL;        //映射后的显存基地址

/********************************************************************
 * 函数名称: show_bmp_image
 * 功能描述: 在LCD上显示指定的BMP图片
 * 输入参数: 文件路径
 * 返 回 值: 成功返回0, 失败返回-1
 ********************************************************************/
static int show_bmp_image(const char *path)
{
    bmp_file_header file_h;
    bmp_info_header info_h;
    unsigned short *line_buf = NULL;    //行缓冲区
    unsigned long line_bytes;   //BMP图像一行的字节的大小
    unsigned int min_h, min_bytes;
    unsigned short *base = screen_base;
    unsigned int bytes_per_pixel = fb_var.bits_per_pixel / 8;
    unsigned int width = fb_fix.line_length / bytes_per_pixel;
    unsigned int line_length = bytes_per_pixel * fb_var.xres;
    int fd = -1;
    int j;

    /* 打开文件 */
    if (0 > (fd = open(path, O_RDONLY))) {
        perror("open error");
        return -1;
    }

    /* 读取BMP文件头 */
    if (sizeof(bmp_file_header) !=
        read(fd, &file_h, sizeof(bmp_file_header))) {
        perror("read error");
        close(fd);
        return -1;
    }

    if (0 != memcmp(file_h.type, "BM", 2)) {
        fprintf(stderr, "it's not a BMP file\n");
        close(fd);
        return -1;
    }

    /* 读取位图信息头 */
    if (sizeof(bmp_info_header) !=
        read(fd, &info_h, sizeof(bmp_info_header))) {
        perror("read error");
        close(fd);
        return -1;
    }

    /* 打印信息 */
    printf("文件大小: %d\n"
         "位图数据的偏移量: %d\n"
         "位图信息头大小: %d\n"
         "图像分辨率: %d*%d\n"
         "像素深度: %d\n", file_h.size, file_h.offset,
         info_h.size, info_h.width, info_h.height,
         info_h.bpp);

    /* 将文件读写位置移动到图像数据开始处 */
    if (-1 == lseek(fd, file_h.offset, SEEK_SET)) {
        perror("lseek error");
        close(fd);
        return -1;
    }

    /* 申请一个buf、暂存bmp图像的一行数据 */
    line_bytes = info_h.width * info_h.bpp / 8;
    line_buf = malloc(line_bytes);
    if (NULL == line_buf) {
        fprintf(stderr, "malloc error\n");
        close(fd);
        return -1;
    }

    if (line_length > line_bytes)
        min_bytes = line_bytes;
    else
        min_bytes = line_length;

    /**** 读取图像数据显示到LCD ****/
    /*******************************************
     * 为了软件处理上方便,这个示例代码便不去做兼容性设计了
     * 如果你想做兼容, 可能需要判断传入的BMP图像是565还是888
     * 如何判断呢?文档里边说的很清楚了
     * 我们默认传入的bmp图像是RGB565格式
     *******************************************/
    if (0 < info_h.height) {//倒向位图
        if (info_h.height > fb_var.yres) {
            min_h = fb_var.yres;
            lseek(fd, (info_h.height - fb_var.yres) * line_bytes, SEEK_CUR);
            base += width * (fb_var.yres - 1);    //定位到屏幕左下角位置
        }
        else {
            min_h = info_h.height;
            base += width * (info_h.height - 1); //定位到....不知怎么描述 懂的人自然懂!
        }

        for (j = min_h; j > 0; base -= width, j--) {
            read(fd, line_buf, line_bytes); //读取出图像数据
            memcpy(base, line_buf, min_bytes);//刷入LCD显存
        }
    }
    else {  //正向位图
        int temp = 0 - info_h.height;   //负数转成正数
        if (temp > fb_var.yres)
            min_h = fb_var.yres;
        else
            min_h = temp;

        for (j = 0; j < min_h; j++, base += width) {
            read(fd, line_buf, line_bytes);
            memcpy(base, line_buf, min_bytes);
        }
    }

    /* 关闭文件、函数返回 */
    close(fd);
    free(line_buf);
    return 0;
}

int main(int argc, char *argv[])
{
    unsigned int screen_size;
    int fd;

    /* 传参校验 */
    if (2 != argc) {
        fprintf(stderr, "usage: %s <bmp_file>\n", argv[0]);
        exit(-1);
    }

    /* 打开framebuffer设备 */
    if (0 > (fd = open("/dev/fb0", O_RDWR))) {
        perror("open error");
        exit(EXIT_FAILURE);
    }

    /* 获取参数信息 */
    ioctl(fd, FBIOGET_VSCREENINFO, &fb_var);
    ioctl(fd, FBIOGET_FSCREENINFO, &fb_fix);
    screen_size = fb_fix.line_length * fb_var.yres;

    /* 将显示缓冲区映射到进程地址空间 */
    screen_base = mmap(NULL, screen_size, PROT_WRITE, MAP_SHARED, fd, 0);
    if (MAP_FAILED == (void *)screen_base) {
        perror("mmap error");
        close(fd);
        exit(EXIT_FAILURE);
    }

    /* 显示BMP图片 */
    memset(screen_base, 0xFF, screen_size);
    show_bmp_image(argv[1]);

    /* 退出 */
    munmap(screen_base, screen_size);  //取消映射
    close(fd);  //关闭文件
    exit(EXIT_SUCCESS);    //退出进程
}

4.2JPG格式

本文作者:hello

本文链接:https://www.cnblogs.com/feige-c/p/16444406.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   feige_c  阅读(254)  评论(1编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起