C语言读取一个bmp文件,将灰度值保存到数组里面
时间: 2023-05-29 16:02:50 浏览: 114
以下是一个简单的C语言程序,用于读取一个bmp文件,并将其灰度值保存到一个数组中:
```c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
// 位图文件头结构体
typedef struct {
uint16_t bfType; // 位图文件类型,必须为"BM"
uint32_t bfSize; // 位图文件大小,以字节为单位
uint16_t bfReserved1; // 保留,必须为0
uint16_t bfReserved2; // 保留,必须为0
uint32_t bfOffBits; // 从文件头到像素数据的偏移量,以字节为单位
} BITMAPFILEHEADER;
// 位图信息头结构体
typedef struct {
uint32_t biSize; // 位图信息头大小,以字节为单位
int32_t biWidth; // 图像宽度,以像素为单位
int32_t biHeight; // 图像高度,以像素为单位
uint16_t biPlanes; // 必须为1
uint16_t biBitCount; // 每个像素的位数,必须是1, 4, 8或24
uint32_t biCompression; // 压缩类型,0为不压缩
uint32_t biSizeImage; // 图像大小,以字节为单位
int32_t biXPelsPerMeter; // 水平分辨率,以像素/米为单位
int32_t biYPelsPerMeter; // 垂直分辨率,以像素/米为单位
uint32_t biClrUsed; // 实际使用的调色板索引数,0为使用所有调色板索引
uint32_t biClrImportant; // 对图像显示有重要影响的颜色索引数,0表示所有颜色都是重要的
} BITMAPINFOHEADER;
// 读取位图文件头
BITMAPFILEHEADER read_file_header(FILE* fp) {
BITMAPFILEHEADER header;
fread(&header.bfType, sizeof(header.bfType), 1, fp);
fread(&header.bfSize, sizeof(header.bfSize), 1, fp);
fread(&header.bfReserved1, sizeof(header.bfReserved1), 1, fp);
fread(&header.bfReserved2, sizeof(header.bfReserved2), 1, fp);
fread(&header.bfOffBits, sizeof(header.bfOffBits), 1, fp);
return header;
}
// 读取位图信息头
BITMAPINFOHEADER read_info_header(FILE* fp) {
BITMAPINFOHEADER header;
fread(&header.biSize, sizeof(header.biSize), 1, fp);
fread(&header.biWidth, sizeof(header.biWidth), 1, fp);
fread(&header.biHeight, sizeof(header.biHeight), 1, fp);
fread(&header.biPlanes, sizeof(header.biPlanes), 1, fp);
fread(&header.biBitCount, sizeof(header.biBitCount), 1, fp);
fread(&header.biCompression, sizeof(header.biCompression), 1, fp);
fread(&header.biSizeImage, sizeof(header.biSizeImage), 1, fp);
fread(&header.biXPelsPerMeter, sizeof(header.biXPelsPerMeter), 1, fp);
fread(&header.biYPelsPerMeter, sizeof(header.biYPelsPerMeter), 1, fp);
fread(&header.biClrUsed, sizeof(header.biClrUsed), 1, fp);
fread(&header.biClrImportant, sizeof(header.biClrImportant), 1, fp);
return header;
}
// 读取位图像素数据,返回灰度值数组
unsigned char* read_pixels(FILE* fp, BITMAPINFOHEADER info_header) {
// 计算每一行像素占用的字节数
int row_bytes = (info_header.biBitCount * info_header.biWidth + 31) / 32 * 4;
// 分配内存并读取像素数据
unsigned char* pixels = (unsigned char*)malloc(info_header.biHeight * info_header.biWidth);
int i, j;
for (i = 0; i < info_header.biHeight; i++) {
// 计算当前行的灰度值,并保存到数组中
for (j = 0; j < info_header.biWidth; j++) {
unsigned char bgr[3];
fread(bgr, 1, 3, fp);
pixels[i * info_header.biWidth + j] = 0.299 * bgr[2] + 0.587 * bgr[1] + 0.114 * bgr[0];
}
// 跳过当前行的填充字节
fseek(fp, row_bytes - info_header.biWidth * 3, SEEK_CUR);
}
return pixels;
}
int main(int argc, char* argv[]) {
if (argc < 2) {
printf("Usage: %s filename\n", argv[0]);
return 1;
}
FILE* fp = fopen(argv[1], "rb");
if (fp == NULL) {
printf("Failed to open file: %s\n", argv[1]);
return 1;
}
BITMAPFILEHEADER file_header = read_file_header(fp);
BITMAPINFOHEADER info_header = read_info_header(fp);
printf("Image size: %dx%d\n", info_header.biWidth, info_header.biHeight);
unsigned char* pixels = read_pixels(fp, info_header);
// 在这里,灰度值数组已经读取完毕,可以进行后续处理了
// ...
free(pixels);
fclose(fp);
return 0;
}
```
注意,上面的程序只能处理24位真彩色位图,对于其他格式的bmp文件可能会出错,需要进行适当的修改。同时,需要注意读取像素数据时跳过的填充字节,以及灰度值的计算方法。