设计一个将24位色深的bmp图片显示到lcd屏幕上,可移植,该程序自己写过之后,又经过了ai的完善和修复后,自己又再次添加一些语句注释
[code]/**************************************************************************** * * file name: 2025-07-30_filecopy.c * author : 15515376695@163.com * date : 2025-07-30 * function : 该程序实现BMP图片信息的读取,且显示在lcd屏幕上 * note : None * CopyRight (c) 2025 15515376695@163.com Right Reseverd * ****************************************************************************/#include #include #include #include #include #include #include #include #include #pragma pack(1)// BMP文件头(14字节)typedef struct { unsigned short bfType; // 必须为0x4D42("BM"标识) unsigned int bfSize; // 文件总大小(字节) unsigned short bfReserved1; // 保留字段,0 unsigned short bfReserved2; // 保留字段,0 unsigned int bfOffBits; // 像素数据偏移量(从文件头开始)} BITMAPFILEHEADER;// BMP信息头(40字节,Windows格式)typedef struct { unsigned int biSize; // 信息头大小(40字节) int biWidth; // 图像宽度(像素) int biHeight; // 图像高度(像素,负数表示从上到下存储) unsigned short biPlanes; // 必须为1 unsigned short biBitCount; // 色深(每像素位数) unsigned int biCompression;// 压缩方式(0表示不压缩) unsigned int biSizeImage; // 像素数据大小(字节,0表示不压缩时可忽略) int biXPelsPerMeter; // 水平分辨率(像素/米) int biYPelsPerMeter; // 垂直分辨率(像素/米) unsigned int biClrUsed; // 使用的颜色数(0表示全部) unsigned int biClrImportant; // 重要颜色数(0表示全部)} BITMAPINFOHEADER;#pragma pack()int main(int argc, char const *argv[]) { // 1. 检查命令行参数 if (argc != 2) { fprintf(stderr, "用法: %s \n", argv[0]); return -1; } // 2. 打开BMP文件并验证合法性 FILE *bmp_fp = fopen(argv[1], "rb"); if (bmp_fp == NULL) { perror("无法打开BMP文件"); return -1; } // 3. 读取并验证BMP文件头 BITMAPFILEHEADER file_header; if (fread(&file_header, sizeof(BITMAPFILEHEADER), 1, bmp_fp) != 1) { perror("读取BMP文件头失败"); fclose(bmp_fp); return -1; } if (file_header.bfType != 0x4D42) { // "BM"的十六进制表示 fprintf(stderr, "错误:不是BMP文件(标识不符)\n"); fclose(bmp_fp); return -1; } // 4. 读取并验证BMP信息头 BITMAPINFOHEADER info_header; if (fread(&info_header, sizeof(BITMAPINFOHEADER), 1, bmp_fp) != 1) { perror("读取BMP信息头失败"); fclose(bmp_fp); return -1; } // 仅支持24位色、不压缩的BMP if (info_header.biBitCount != 24) { fprintf(stderr, "错误:仅支持24位色BMP(当前色深:%d位)\n", info_header.biBitCount); fclose(bmp_fp); return -1; } if (info_header.biCompression != 0) { fprintf(stderr, "错误:仅支持无压缩BMP(当前压缩方式:%d)\n", info_header.biCompression); fclose(bmp_fp); return -1; } // 5. 获取BMP宽高(处理高度可能为负数的情况) int bmp_width = info_header.biWidth; int bmp_height = abs(info_header.biHeight); // 取绝对值(高度符号表示存储方向) printf("BMP信息:宽=%dpx,高=%dpx,像素数据偏移量=%d字节\n", bmp_width, bmp_height, file_header.bfOffBits); // 6. 计算BMP每行实际字节数(必须是4的倍数,含填充字节) int line_bytes = (bmp_width * 3 + 3) / 4 * 4; // 向上取4的倍数 int pixel_data_size = line_bytes * bmp_height; // 总像素数据大小(含填充) // 7. 分配内存存储像素数据(堆内存,避免栈溢出) unsigned char *bmp_pixels = malloc(pixel_data_size);//pixels是像素的意思 if (bmp_pixels == NULL) { perror("内存分配失败"); fclose(bmp_fp); return -1; } // 8. 定位到像素数据位置并读取 if (fseek(bmp_fp, file_header.bfOffBits, SEEK_SET) != 0) { perror("定位到像素数据失败"); free(bmp_pixels); fclose(bmp_fp); return -1; } if (fread(bmp_pixels, 1, pixel_data_size, bmp_fp) != pixel_data_size) { perror("读取像素数据失败"); free(bmp_pixels); fclose(bmp_fp); return -1; } fclose(bmp_fp); // 像素数据已读取,关闭BMP文件 // 9. 打开LCD设备(framebuffer) int lcd_fd = open("/dev/fb0", O_RDWR); if (lcd_fd == -1) { perror("无法打开LCD设备(/dev/fb0)"); free(bmp_pixels); return -1; } // 10. 内存映射LCD(假设LCD分辨率与BMP一致,实际可通过ioctl获取) int lcd_size = bmp_width * bmp_height * 4; // 每个像素4字节(ARGB) int *lcd_mp = (int *)mmap(NULL, lcd_size, PROT_READ | PROT_WRITE, MAP_SHARED, lcd_fd, 0); if (lcd_mp == MAP_FAILED) { perror("LCD内存映射失败"); close(lcd_fd); free(bmp_pixels); return -1; } // 11. 像素转换与显示(处理BMP存储方向) for (int y = 0; y < bmp_height; y++) { // BMP高度为正数时,像素数据从上到下存储的是图像的底部到顶部,需翻转y轴 int bmp_y = (info_header.biHeight > 0) ? (bmp_height - 1 - y) : y; //条件 ? 表达式1 : 表达式2 //实现了行索引的翻转 //意思是:如果 “条件” 为真(非 0),就返回 “表达式 1” 的结果;否则返回 “表达式 2” 的结果。 for (int x = 0; x < bmp_width; x++) { // 计算BMP每个像素在内存中所对应的位置(跳过每行填充字节) int bmp_idx = bmp_y * line_bytes + x * 3; // BMP像素格式:BGR,转换为LCD的ARGB(Alpha=0xFF表示不透明) unsigned char b = bmp_pixels[bmp_idx];//blue unsigned char g = bmp_pixels[bmp_idx + 1];//green unsigned char r = bmp_pixels[bmp_idx + 2];//red //进行偏移成argb的色彩与lcd对应 int argb = 0xFF000000 | (r |