C语言实现clut8bpp格式图片

本文详细介绍了BMP图像文件的结构,包括bmp_file_header、bmp_info_header、可能存在的BMP_Color结构以及DIB数据区。通过C语言代码展示了如何创建一个8位深度的240x320像素BMP文件,从文件头到数据区的编写过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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的文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值