02内存映射与bmp解码
- 手机
- 2025-09-20 14:39:01

一、mmap 内存映射
内存映射的作用是把硬件设备的地址,映射到应用层的内存空间,这样用户就可以跨越系统层访问linux的硬件设备。
1、man 2 mmap 查看映射函数接口 NAME mmap, munmap - map or unmap files or devices into memory 映射 解除映射 文件 或 设备 到 内存 SYNOPSIS #include <sys/mman.h> void *mmap(void *addr, //内存首地址,NULL 系统自动选择 size_t length, //映射空间的大小,必须大于0 int prot, //👉 PROT_READ | PROT_WRITE int flags, // MAP_SHARED 其他进程可见 MAP_PRIVATE 其他进程不可见 int fd, // 文件描述符 off_t offset); // 偏移量 ,默认为 0 即可 返回值: 成功 映射地址,void *万能指针,用于后续用户强制转换类型! 失败 MAP_FAILED prot操作权限: PROT_EXEC 可执行 PROT_READ 可读 PROT_WRITE 可写 PROT_NONE 没有权限 ⭐映射LCD设备 void *mmap(NULL,800*480*4,PROT_READ | PROT_WRITE,MAP_SHARED ,lcd_fd,0) //解除映射 int munmap(void *addr, size_t length); addr:映射地址 length:映射内存的大小 2、内存映射demo #include <stdio.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main() { int lcd_fd = open("/dev/fb0", O_RDWR); if (lcd_fd < 0) { printf("LCD设备打开失败\n"); return -1; } // 映射LCD设备 void *p = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, lcd_fd, 0); if (p == MAP_FAILED) { printf("映射失败\n"); return -1; } else { printf("映射成功\n"); } } 3、映射地址与LCD关系 #if ONE // 把映射地址强制转换 int *lcd = p; while (1) { // 一个一个像素点赋值到LCD设备中 for (int x = 0; x < 800 * 480; x++) { lcd[x] = 0x0000ff; } sleep(1); for (int x = 0; x < 800 * 480; x++) { lcd[x] = 0x00ff00; } sleep(1); } #endif #if TWO // 把映射地址强制转换 int(*lcd)[800] = p; for (int y = 0; y < 480; y++) { for (int x = 0; x < 800; x++) { lcd[y][x] = 0xff00ff; } } #endif 二、lcd显示bmp图片 1、计算机常见的图片格式 JPG(JPEG)、PNG和BMP是常见的图像文件格式,它们各有特点和适用场景: JPG(JPEG) 压缩方式:JPEG使用有损压缩,这意味着在压缩过程中会丢失一些图像数据,尤其是当压缩比率较高时。 适用场景:由于有损压缩,JPEG文件通常比PNG和BMP文件小,适合网络传输和存储空间有限的情况。它非常适合照片和复杂图像,因为这些图像的微小失真通常人眼难以察觉。 颜色深度:JPEG支持最高为24位的颜色深度。 透明度:JPEG不支持透明背景。 PNG(Portable Network Graphics) 压缩方式:PNG使用无损压缩,它可以在不损失任何图像数据的情况下压缩图像。 适用场景:PNG非常适合网页设计、图标和其他需要高保真度图像的场合。它的文件大小通常比JPEG大,但比BMP小。 颜色深度:PNG支持最高达48位的真彩色,并且支持灰度图像、索引颜色图像。 透明度:PNG支持透明背景和半透明效果,这是它的一大优势。 BMP(Bitmap) 压缩方式:BMP通常不使用压缩,它直接存储每个像素的颜色信息,因此文件大小通常很大。 适用场景:BMP格式因其简单和直接性在某些特定场合(如Windows系统中的图标)被使用,但由于文件体积大,不适合网络传输。 颜色深度:BMP支持多种颜色深度,包括24位和32位真彩色。 透明度:标准的BMP格式不支持透明度,但Windows位图可以包含alpha通道来支持透明度。 总结来说,选择哪种格式取决于图像的使用场景和对图像质量的要求。如果需要小文件体积且可以接受一定的质量损失,JPEG是不错的选择;如果需要高保真度和透明度支持,PNG是更好的选择;而BMP由于文件体积大,通常只在特定场合使用。 2、BMP 图片格式通过上述方法调整图片的格式。
bmp文件头 //bmp文件头结构体-》占用14个字节 struct bitmap_header { int16_t type; int32_t size; // 图像文件大小 int16_t reserved1; int16_t reserved2; int32_t offbits; // bmp图像数据偏移量 }__attribute__((packed)); //bmp位图信息头结构体 -》占用40个字节 struct bitmap_info { int32_t size; // 本结构大小 int32_t width; // 图像宽 int32_t height; // 图像高 int16_t planes; int16_t bit_count; // 色深 int32_t compression; int32_t size_img; // bmp数据大小,必须是4的整数倍 int32_t X_pel; int32_t Y_pel; int32_t clrused; int32_t clrImportant; }__attribute__((packed)); 用户在读取像素数据之前,应该把上述的54个字节先读取出来,再读取像素数据! __attribute__((packed)); 把结构体压实,不进行任何的字节对齐方式! bmp头数据处理demo #include <stdio.h> #include <sys/types.h> //在该头文件中定义了 int16_t int32_t #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> // bmp文件头结构体-》占用14个字节 struct bitmap_header { int16_t type; int32_t size; // 图像文件大小 int16_t reserved1; int16_t reserved2; int32_t offbits; // bmp图像数据偏移量 } __attribute__((packed)); // bmp位图信息头结构体 -》占用40个字节 struct bitmap_info { int32_t size; // 本结构大小 int32_t width; // 图像宽 int32_t height; // 图像高 int16_t planes; int16_t bit_count; // 色深 int32_t compression; int32_t size_img; // bmp数据大小,必须是4的整数倍 int32_t X_pel; int32_t Y_pel; int32_t clrused; int32_t clrImportant; } __attribute__((packed)); int main() { printf("sizeof(struct bitmap_header)=%ld\n", sizeof(struct bitmap_header)); // 12 printf("sizeof(struct bitmap_info)=%ld\n", sizeof(struct bitmap_info)); // 40 // 1.打开图片文件 int bmp_fd = open("tm.bmp", O_RDWR); if (bmp_fd < 0) { printf("打开图片失败\n"); return -1; } // 2.读取14个字节头数据 struct bitmap_header head; read(bmp_fd, &head, 14); struct bitmap_info info; read(bmp_fd, &info, 40); int widht = info.width; int height = info.height; int bbp = info.bit_count; printf("大小 %d 宽度 %d 高度 %d 色深 %d\n", head.size, widht, height, bbp); } 3、bmp 像素数据处理 // 像素缓存区 char rgb[widht * 3 * height]; read(bmp_fd, rgb, sizeof(rgb)); // 把rgb的数据转换为argb数据 char argb[800 * 4 * 480]; for (int i = 0; i < 800 * 480; i++) { argb[0 + i * 4] = rgb[0 + i * 3]; argb[1 + i * 4] = rgb[1 + i * 3]; argb[2 + i * 4] = rgb[2 + i * 3]; argb[3 + i * 4] = 0; } 4、LCD 映射显示argb数据 #include <stdio.h> #include <sys/mman.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> // bmp文件头结构体-》占用14个字节 struct bitmap_header { int16_t type; int32_t size; // 图像文件大小 int16_t reserved1; int16_t reserved2; int32_t offbits; // bmp图像数据偏移量 } __attribute__((packed)); // bmp位图信息头结构体 -》占用40个字节 struct bitmap_info { int32_t size; // 本结构大小 int32_t width; // 图像宽 int32_t height; // 图像高 int16_t planes; int16_t bit_count; // 色深 int32_t compression; int32_t size_img; // bmp数据大小,必须是4的整数倍 int32_t X_pel; int32_t Y_pel; int32_t clrused; int32_t clrImportant; } __attribute__((packed)); int main() { int lcd_fd = open("/dev/fb0", O_RDWR); if (lcd_fd < 0) { printf("LCD设备打开失败\n"); return -1; } // 映射LCD设备 void *p = mmap(NULL, 800 * 480 * 4, PROT_READ | PROT_WRITE, MAP_SHARED, lcd_fd, 0); if (p == MAP_FAILED) { printf("映射失败\n"); return -1; } else { printf("映射成功\n"); } // 1.打开图片文件 int bmp_fd = open("tm.bmp", O_RDWR); if (bmp_fd < 0) { printf("打开图片失败\n"); return -1; } // 2.读取14个字节头数据 struct bitmap_header head; read(bmp_fd, &head, 14); struct bitmap_info info; read(bmp_fd, &info, 40); int widht = info.width; int height = info.height; int bbp = info.bit_count; printf("大小 %d 宽度 %d 高度 %d 色深 %d\n", head.size, widht, height, bbp); // 像素缓存区 char rgb[widht * 3 * height]; read(bmp_fd, rgb, sizeof(rgb)); // 把rgb的数据转换为argb数据 char argb[800 * 4 * 480]; for (int i = 0; i < 800 * 480; i++) { argb[0 + i * 4] = rgb[0 + i * 3]; argb[1 + i * 4] = rgb[1 + i * 3]; argb[2 + i * 4] = rgb[2 + i * 3]; argb[3 + i * 4] = 0; } // 转换映射地址 char *lcd = p; for (int i = 0; i < 800 * 4 * 480; i++) { lcd[i] = argb[i]; // 把argb这些数据放入LCD映射地址 } // 关闭图片 close(bmp_fd); close(lcd_fd); // 解除映射 munmap(lcd, 800 * 4 * 480); }至此,希望看完这篇文章的你有所收获,我是Bardb,译音八分贝,道友,下期见!
02内存映射与bmp解码由讯客互联手机栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“02内存映射与bmp解码”