bmp文件结构解析:
一个bmp图片最多由4大部分组成:bmp_file_header结构体,bmp_info_header结构体,BMP_Color结构体(这个结构体可以有,也可以没有), DIB数据区。其中DIB意思就是Device-Independent Bitmap(设备无关位图)。所有的DIB数据扫描行是上下颠倒的,也就是说一幅图片先绘制底部的像素,再绘制顶部的像素,所以这些DIB数据所表示的像素点就是从图片的左下角开始,一直表示到图片的右上角。
代码如下
#include <stdio.h>
#include <stdint.h>
struct bmp_info_header {
unsigned int biSize;//位图信息头长度,指定此结构体的长度,为40
unsigned int biWidth;//位图宽度,以像素为单位
unsigned int biHeight;//位图高度,以像素为单位
unsigned short biPlanes;//位图的位面数,该值总是1
unsigned short biBitCount;//每个像素的位数。有1(单色),4(16色),8(256色),16(64K色,高彩色),24(16M色,真彩色),32(4096M色,增强型真彩色)
unsigned int biCompression;//压缩说明:有0(不压缩),1(RLE 8,8位RLE压缩),2(RLE 4,4位RLE压缩,3(Bitfields,位域存放)
unsigned int biSizeImage;//用字节数表示的位图数据的大小,该数必须是4的倍数, 数值上等于(≥位图宽度的最小的4的倍数)×位图高度×每个像素位数
unsigned int biXPelsPerMeter;//用象素/米表示的 水平分辨率
unsigned int biYPelsPerMeter;//用象素/米表示的垂直 分辨率
unsigned int biClrUsed;//使用的颜色数,如果为0,则表示默认值(2^颜色位数),即使用所有调色板
unsigned int biClrImportant; //重要颜色数,如果为0,则表示所有颜色都是重要的
} __attribute__((packed));
struct bmp_file_header {
unsigned short bfType;//固定为0x4d42,即“BM”,其中M为高位,B为低位;
unsigned int bfSize; //整个文件大小
unsigned short bfReserved1;//保留,必须设置为0。
unsigned short bfReserved2;//保留,必须设置为0。
unsigned int bfOffBits;//实际位图数据的偏移字节数,即前三个部分长度之和
} __attribute__((packed));//共14字节
#define WIDTH 224
#define HEIGHT 320
#define PALETTE_SIZE 256
typedef struct {
unsigned char blue; //该颜色的蓝色分量
unsigned char green;//该颜色的绿色分量
unsigned char red;//该颜色的红色分量
unsigned char reserved; // BMP palette may include an extra reserved byte
} BMP_Color;
int main() {
const char bmp_file_type[] = {'B', 'M'};
const size_t palette_size = PALETTE_SIZE * sizeof(BMP_Color);
const size_t bmp_size = sizeof(struct bmp_file_header) + sizeof(struct bmp_info_header) + palette_size + (WIDTH * HEIGHT);
// File header
struct bmp_file_header file_header = {
bfType: bmp_file_type[0] | (bmp_file_type[1] << 8),
bfSize: bmp_size,
bfReserved1: 0,
bfReserved2: 0,
bfOffBits: sizeof(struct bmp_file_header) + sizeof(struct bmp_info_header) + palette_size
};
// Info header
struct bmp_info_header info_header = {
biSize: sizeof(struct bmp_info_header),
biWidth: WIDTH,
biHeight: HEIGHT,
biPlanes: 1,
biBitCount: 8,
biCompression: 0, // 0 or 3 for no compression
biSizeImage: WIDTH * HEIGHT,
biXPelsPerMeter: 0, // No resolution information
biYPelsPerMeter: 0,
biClrUsed: PALETTE_SIZE,
biClrImportant: PALETTE_SIZE
};
// Create the BMP file
FILE *bmp = fopen("240x320_8BPP.bmp", "wb");
if (!bmp) {
perror("Error opening file");
return 1;
}
// Write the file header
fwrite(&file_header, sizeof(struct bmp_file_header), 1, bmp);
// Write the info header
fwrite(&info_header, sizeof(struct bmp_info_header), 1, bmp);
// Create and write the color palette
BMP_Color palette[PALETTE_SIZE] = {0};
for (int i = 0; i < PALETTE_SIZE; ++i) {
palette[i].red = 255;
palette[i].green = 0;
palette[i].blue = 0;
}
fwrite(palette, sizeof(BMP_Color), PALETTE_SIZE, bmp);
// Create and write the pixel data
unsigned char pixel_data[WIDTH * HEIGHT] = {0};
// Fill pixel_data with values 0 to 255 and use as indexes into the palette
for (int y = 0; y < HEIGHT; ++y) {
for (int x = 0; x < WIDTH; ++x) {
pixel_data[y * WIDTH + x] = (x + y) % PALETTE_SIZE;
}
}
// BMP files are written from bottom to top
fwrite(pixel_data, HEIGHT, WIDTH, bmp);
// Close the file
fclose(bmp);
return 0;
}
gcc -o gen_bmp gen_bmp.c
生成可执行文件后,执行./gen_bmp会生成名为240x320_8BPP.bmp的文件。