显示 BMP 图片
BMP 图像介绍BMPBitmap是 Windows 操作系统中的标准图像文件格式文件后缀名为 .bmp。它采用位映射存储格式图像数据没有进行任何压缩因此文件占用空间大但无失真、解析简单。BMP 图像深度可选1bit、4bit、8bit、16bit、24bit、32bit。典型的 BMP 文件由以下四部分组成数据段 大小 说明BMP 文件头 14 字节 文件格式、大小、位图数据偏移量位图信息头 通常 40 或 56 字节 尺寸、位深度、压缩方式、颜色索引调色板 由颜色索引数决定 可选索引到颜色的映射表位图数据 由图像尺寸决定 图像原始数据真彩色图像16位、24位、32位不需要调色板位图信息头后面紧跟位图数据。BMP 文件头结构typedef struct tagBITMAPFILEHEADER {UINT16 bfType; /* 文件类型“BM” 表示 Windows 位图/DWORD bfSize; /文件大小字节/UINT16 bfReserved1; /保留必须为 0/UINT16 bfReserved2; /保留必须为 0/DWORD bfOffBits; /从文件起始到位图数据的字节偏移量/} BITMAPFILEHEADER;位图信息头结构typedef struct tagBITMAPINFOHEADER {DWORD biSize; /位图信息头大小/LONG biWidth; /图像宽度像素/LONG biHeight; /图像高度像素正数为倒向位图负数为正向位图/WORD biPlanes; /色彩平面数总为 1/WORD biBitCount; /像素深度1/4/8/16/24/32/DWORD biCompression; /压缩类型0RGB, 3Bit-Fields/DWORD biSizeImage; /图像数据大小/LONG biXPelsPerMeter; /水平分辨率像素/米/LONG biYPelsPerMeter; /垂直分辨率像素/米/DWORD biClrUsed; /实际使用的颜色索引数/DWORD biClrImportant; /重要颜色索引数 */} BITMAPINFOHEADER;正向位图与倒向位图正向位图biHeight 为负数图像数据按左上角到右下角排列水平从左到右垂直从上到下。倒向位图biHeight 为正数图像数据按左下角到右上角排列水平从左到右垂直从下到上。大多数 BMP 图像为倒向位图。RGB 与 Bit-Fields 编码对于 16bpp 及以上的位图不使用调色板有两种编码格式RGB 编码R、G、B 三种颜色信息容量均分如 24bpp 各占 8 位。Bit-FieldsBF编码利用位域掩码确定 RGB 三分量的信息容量。当压缩方式为 BFbiCompression3时位图信息头大小为 56 字节多出的 16 字节为 R、G、B、A 四个分量的位域掩码。A 分量即 Alpha透明度 通道取值范围 0~2550 表示完全透明255 表示完全不透明。在 BMP 中通常无实际意义但 ARGB8888 格式会占 8 位。位域掩码的作用指出 R、G、B或 A各分量在一个像素值中分别占多少位、位于什么位置。通过掩码即可从像素值中提取或组合出各颜色分量从而动态判断像素格式。对于 RGB565 格式R、G、B 的位域掩码分别为 0xF800、0x07E0、0x001FR 通道高 5 位bit 15~11G 通道中间 6 位bit 10~5B 通道低 5 位bit 4~0在 LCD 上显示 BMP 图像显示 BMP 图像的核心思路解析 BMP 文件头和位图信息头读取位图数据然后写入 LCD 显存。示例代码#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/**** BMP 文件头数据结构 ****/typedef struct {unsigned char type[2];unsigned int size;unsigned short reserved1;unsigned short reserved2;unsigned int offset;}attribute((packed)) bmp_file_header;/**** 位图信息头数据结构 ***/typedef struct {unsigned int size;int width;int height;unsigned short planes;unsigned short bpp; /bits per pixel每个像素占多少位 */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 int width;static int height;static unsigned short *screen_base NULL;static unsigned long line_length;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;unsigned int min_h, min_bytes;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, its 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; // bpp ÷ 8 将位(bit)转为字节(Byte) line_buf malloc(line_bytes); if (NULL line_buf) { fprintf(stderr, malloc error\n); close(fd); return -1; } if (line_length line_bytes) // line_length: LCD一行字节数 min_bytes line_bytes; // line_bytes: BMP一行字节数 else // 取较小值防止memcpy越界 min_bytes line_length; /* 读取图像数据显示到 LCD */ if (0 info_h.height) { // 倒向位图 if (info_h.height height) { min_h height; lseek(fd, (info_h.height - height) * line_bytes, SEEK_CUR); screen_base width * (height - 1); } else { min_h info_h.height; screen_base width * (info_h.height - 1); } for (j min_h; j 0; screen_base - width, j--) { read(fd, line_buf, line_bytes); memcpy(screen_base, line_buf, min_bytes); } } else { // 正向位图 int temp 0 - info_h.height; if (temp height) min_h height; else min_h temp; for (j 0; j min_h; j, screen_base width) { read(fd, line_buf, line_bytes); memcpy(screen_base, line_buf, min_bytes); } } close(fd); free(line_buf); return 0;}int main(int argc, char *argv[]){struct fb_fix_screeninfo fb_fix;struct fb_var_screeninfo fb_var;unsigned int screen_size;int fd;if (2 ! argc) { fprintf(stderr, usage: %s bmp_file\n, argv[0]); exit(-1); } 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; line_length fb_fix.line_length; width fb_var.xres; height 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); } memset(screen_base, 0xFF, screen_size); show_bmp_image(argv[1]); munmap(screen_base, screen_size); close(fd); exit(EXIT_SUCCESS);}显示 BMP 的主要流程打开 BMP 文件读取文件头和位图信息头。校验文件类型是否为 “BM”。通过 lseek() 将文件读写位置移至图像数据起始处file_h.offset。根据 info_h.height 判断正向/倒向位图逐行读取图像数据并 memcpy 到显存映射区。关闭文件释放资源。注意示例代码默认传入的 BMP 图像为 RGB565 格式。如需兼容 RGB888 等其他格式需根据 bmp_info_header 中的 compression 和位域掩码进行判断处理。

相关新闻

大语言模型文本长度控制:LIFEBench基准测试解析

大语言模型文本长度控制:LIFEBench基准测试解析

1. 项目概述:LIFEBench基准测试的核心价值大语言模型(LLMs)在解决复杂推理任务方面展现出惊人能力,却在一个看似简单的功能上频繁翻车——按照指定长度生成文本。当用户要求"写一篇5000字的行业分析"时,模型…

2026/10/16 4:11:28 阅读更多 →
C++与Qt字符串传参性能优化:值传递、引用与COW机制详解

C++与Qt字符串传参性能优化:值传递、引用与COW机制详解

1. 项目概述:从一次性能调优说起最近在重构一个历史遗留的C/Qt项目时,遇到了一个典型的性能瓶颈。一个核心的数据处理模块,在处理大量文本数据时,CPU占用率异常高。经过Profile工具(如perf或Qt Creator自带的分析器&am…

2026/10/15 21:08:16 阅读更多 →
C++搜索引擎核心:基于Boost库的正倒排索引压缩与高性能实现

C++搜索引擎核心:基于Boost库的正倒排索引压缩与高性能实现

1. 项目概述:从零构建一个高性能的C搜索引擎核心 最近在整理过往的项目代码,翻出了一个挺有意思的“老伙计”——一个基于Boost库纯手工打造的C搜索引擎核心模块。这个项目的核心目标非常明确:在有限的内存和磁盘空间下,高效地存储…

2026/10/15 6:48:16 阅读更多 →

最新新闻

大厂7000个实习名额背后:投递、简历、面试与转正全拆解

大厂7000个实习名额背后:投递、简历、面试与转正全拆解

早上起来刷手机,某头部科技公司2025年实习生招聘通道静悄悄开了,但朋友圈和各个求职群瞬间炸了锅——7000个实习生名额,这个数字比不少中小公司的全员编制还多。这几年大家看惯了"缩招""HC冻结"之类的新闻,突…

2026/10/16 5:05:29 阅读更多 →
C# MQTT客户端工程实践:从协议原理到断线重连

C# MQTT客户端工程实践:从协议原理到断线重连

简介:这是一份基于C#实现的MQTT协议客户端完整工程,面向物联网开发者、上位机工程师以及需要学习MQTT通信机制的编程人员,主要解决设备与MQTT服务器之间轻量级发布/订阅消息传输和远程监控需求。工程压缩包共35个文件,包含9个C#源…

2026/10/16 5:05:29 阅读更多 →
VSC-MMC仿真建模实践:原理、参数计算与调试避坑

VSC-MMC仿真建模实践:原理、参数计算与调试避坑

提到基于VSC的MMC仿真,不少刚接触柔性直流的朋友第一反应是“原理图太密、公式太多”。我最初接手这个方向时也一样,看着桥臂上一串子模块,差点劝退。但实际动手搭过一轮仿真之后,我发现只要把“电压源换流器(VSC&…

2026/10/16 5:05:29 阅读更多 →
别再迷信8小时:用睡眠周期和起床时机找到你的最佳睡眠时长

别再迷信8小时:用睡眠周期和起床时机找到你的最佳睡眠时长

先说个我自己的经历。有一阵我特别迷信“睡足8小时”,每天闹钟固定在早上7点,晚上不管困不困都逼自己11点上床。结果呢?半夜频繁醒,早上起来像被人从被窝里硬拖出来一样,白天还得靠两杯咖啡续命。后来有几天加班&#…

2026/10/16 5:05:29 阅读更多 →
大模型不生成视频:从文本到成片的五步制作流水线详解

大模型不生成视频:从文本到成片的五步制作流水线详解

最近“Claude Opus 5.5 能生成视频”的说法在一些技术社区里传得很猛,我刷到好几个帖子,标题一个比一个唬人,点进去一看,要么是把模型生成的动画代码误当成“视频指令”,要么直接拿某个渲染结果截图说模型出片了。作为…

2026/10/16 5:05:29 阅读更多 →
视觉中间件 VM PRO 2.7:从图像接入到推理调度的视觉开发框架实践指南

视觉中间件 VM PRO 2.7:从图像接入到推理调度的视觉开发框架实践指南

视觉框架 VM PRO 2.7 是我这几个月在好几个视觉项目里反复用下来的一套工具集。它本身不是某个具体的检测算法,也不是一个渲染引擎,而是一套把图像接入、预处理、推理调度、结果后处理、设备适配揉在一起的视觉中间件,行话叫视觉开发框架也行…

2026/10/16 5:04:29 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →