1 图片.bmp数据结构
BMP(Bitmap)文件格式是一种简单的位图图像格式,其数据结构分为几个主要部分:文件头、信息头、调色板(可选)和像素数据。下面是各部分的详细说明。
- 文件头(File Header)
bfType (2 bytes): 文件类型,通常为'BM'(0x42 0x4D)。
bfSize (4 bytes): 文件大小(以字节为单位)。
bfReserved1 (2 bytes): 保留字,通常为0。
bfReserved2 (2 bytes): 保留字,通常为0。
bfOffBits (4 bytes): 从文件头到像素数据的偏移量。
- 信息头(DIB Header)
biSize (4 bytes): 信息头的大小(通常为40)。
biWidth (4 bytes): 图像宽度(以像素为单位)。
biHeight (4 bytes): 图像高度(以像素为单位)。
biPlanes (2 bytes): 色平面数,通常为1。
biBitCount (2 bytes): 每个像素的位数(如24位、32位)。
biCompression (4 bytes): 压缩类型(0为不压缩)。
biSizeImage (4 bytes): 图像数据的大小(可以为0)。
biXPelsPerMeter (4 bytes): 水平分辨率(像素每米)。
biYPelsPerMeter (4 bytes): 垂直分辨率(像素每米)。
biClrUsed (4 bytes): 使用的颜色数(0表示使用所有颜色)。
biClrImportant (4 bytes): 重要的颜色数(0表示所有)。
-
调色板(Color Palette)
对于某些格式(如1位或4位色),可能会包含调色板。调色板由颜色索引组成,使用RGB格式(每个颜色占用4个字节,包含蓝、绿、红、保留字节)。 -
像素数据(Pixel Data)
像素数据从bfOffBits指定的位置开始。像素的排列顺序通常是自下而上,从左到右,具体存储格式取决于biBitCount:
24位BMP:每个像素使用3个字节,分别表示蓝色、绿色和红色(BGR格式)。
32位BMP:每个像素使用4个字节(蓝、绿、红、透明度)。
在C语言中,BMP文件格式有一个特定的数据结构。BMP文件分为文件头、信息头和像素数据。下面是BMP文件的基本数据结构:
BMP 文件数据结构
#include <stdint.h>// BMP 文件头
typedef struct {uint16_t bfType; // 文件类型,通常为 'BM'uint32_t bfSize; // 文件大小uint16_t bfReserved1; // 保留字段uint16_t bfReserved2; // 保留字段uint32_t bfOffBits; // 像素数据的偏移量
} BMPFileHeader;
// BMP 信息头
typedef struct {uint32_t biSize; // 信息头大小int32_t biWidth; // 图像宽度int32_t biHeight; // 图像高度uint16_t biPlanes; // 色平面数,通常为1uint16_t biBitCount; // 每个像素的比特数(如24位)uint32_t biCompression; // 压缩类型uint32_t biSizeImage; // 图像大小int32_t biXPelsPerMeter; // 水平分辨率int32_t biYPelsPerMeter; // 垂直分辨率uint32_t biClrUsed; // 使用的颜色数uint32_t biClrImportant; // 重要的颜色数
} BMPInfoHeader;
// 像素数据
typedef struct {uint8_t blue; // 蓝色分量uint8_t green; // 绿色分量uint8_t red; // 红色分量
} RGBPix
2 解析 BMP 文件步骤
打开 BMP 文件:
FILE *file = fopen("image.bmp", "rb");
if (!file) {perror("Unable to open file");return;
}
读取文件头:
BMPFileHeader fileHeader;
fread(&fileHeader, sizeof(BMPFileHeader), 1, file);
读取信息头:
BMPInfoHeader infoHeader;
fread(&infoHeader, sizeof(BMPInfoHeader), 1, file);
读取像素数据:
根据 infoHeader.biWidth 和 infoHeader.biHeight 读取像素数据。
int row_padded = (infoHeader.biWidth * 3 + 3) & (~3); // 行填充到4的倍数
RGBPixel *pixels = malloc(infoHeader.biWidth * infoHeader.biHeight * sizeof(RGBPixel));for (int i = 0; i < infoHeader.biHeight; i++) {fread(pixels + (infoHeader.biHeight - i - 1) * infoHeader.biWidth, sizeof(RGBPixel), infoHeader.biWidth, file);fseek(file, row_padded - infoHeader.biWidth * 3, SEEK_CUR);
}
关闭文件:
fclose(file);
注意事项
BMP文件通常以蓝色、绿色、红色(BGR)顺序存储像素。
图片数据行通常是4字节对齐,可能需要填充字节。
确保检查文件类型以确认它是一个合法的BMP文件。
3 c语言 .bmp图像读写示例
#include <stdio.h>
#include <stdlib.h>#define BUF_SIZE 720*1280*3
#define IMG_NAME "fengjing720.bmp"
#define IMG_NEW "x1.bmp"#pragma pack(push, 1) // 让结构体按照1字节对齐,确保读写顺序正确
typedef struct {unsigned short bfType; // 文件类型unsigned int bfSize; // 文件大小unsigned short bfReserved1; // 保留字unsigned short bfReserved2; // 保留字unsigned int bfOffBits; // 像素数据偏移
} BITMAPFILEHEADER;typedef struct {unsigned int biSize; // 信息头大小int biWidth; // 图像宽度int biHeight; // 图像高度unsigned short biPlanes; // 平面数unsigned short biBitCount; // 每个像素的位数unsigned int biCompression; // 压缩类型unsigned int biSizeImage; // 图像大小int biXPelsPerMeter; // 水平分辨率int biYPelsPerMeter; // 垂直分辨率unsigned int biClrUsed; // 使用的颜色索引unsigned int biClrImportant; // 重要的颜色索引
} BITMAPINFOHEADER;
#pragma pack(pop)BITMAPFILEHEADER bfHeader;
BITMAPINFOHEADER biHeader;void readBMP(const char *filename,unsigned char *data,int size) {FILE *file = fopen(filename, "rb");if (!file) {perror("Failed to open file");return;}// BITMAPFILEHEADER bfHeader;// BITMAPINFOHEADER biHeader;fread(&bfHeader, sizeof(bfHeader), 1, file);fread(&biHeader, sizeof(biHeader), 1, file);if (bfHeader.bfType != 0x4D42) {printf("Not a BMP file.\n");fclose(file);return;}printf("Width: %d, Height: %d Offset:%d\n", biHeader.biWidth, biHeader.biHeight,bfHeader.bfOffBits);// 移动到像素数据部分fseek(file, bfHeader.bfOffBits, SEEK_SET);// 计算像素数据大小//*size = biHeader.biWidth * biHeader.biHeight * 3; // 24位RGB//unsigned char *data = (unsigned char *)malloc(imageSize);if (!data) {printf("Memory allocation failed\n");fclose(file);return;}fread(data, 1,size, file);fclose(file);// 处理像素数据(例如,打印第一个像素的RGB值)printf("First pixel RGB: (%d, %d, %d)\n", data[0], data[1], data[2]);//free(data);
}void writeBMP( const char *filename,unsigned char *data,int size)
{FILE *file = fopen(filename, "wb");if (!file) {perror("Unable to create file");return;}// 写入文件头和信息头fwrite(&bfHeader, sizeof(bfHeader), 1, file);fwrite(&biHeader, sizeof(biHeader), 1, file);// 写入像素数据fwrite(data, 1,size, file);fclose(file);
}int main() {char img_buf[BUF_SIZE];readBMP(IMG_NAME,img_buf,BUF_SIZE);printf("Width: %d, Height: %d Offset:%d\n", biHeader.biWidth, biHeader.biHeight,bfHeader.bfOffBits);writeBMP(IMG_NEW,img_buf,BUF_SIZE);return 0;
}