c语言 图片.bmp读写示例

发布于:2024-08-13 ⋅ 阅读:(98) ⋅ 点赞:(0)

1 图片.bmp数据结构

BMP(Bitmap)文件格式是一种简单的位图图像格式,其数据结构分为几个主要部分:文件头、信息头、调色板(可选)和像素数据。下面是各部分的详细说明。

  1. 文件头(File Header)
bfType (2 bytes): 文件类型,通常为'BM'0x42 0x4D)。
bfSize (4 bytes): 文件大小(以字节为单位)。
bfReserved1 (2 bytes): 保留字,通常为0bfReserved2 (2 bytes): 保留字,通常为0bfOffBits (4 bytes): 从文件头到像素数据的偏移量。
  1. 信息头(DIB Header)
biSize (4 bytes): 信息头的大小(通常为40)。
biWidth (4 bytes): 图像宽度(以像素为单位)。
biHeight (4 bytes): 图像高度(以像素为单位)。
biPlanes (2 bytes): 色平面数,通常为1biBitCount (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表示所有)。
  1. 调色板(Color Palette)
    对于某些格式(如1位或4位色),可能会包含调色板。调色板由颜色索引组成,使用RGB格式(每个颜色占用4个字节,包含蓝、绿、红、保留字节)。

  2. 像素数据(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;        // 色平面数,通常为1
    uint16_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;
}

在这里插入图片描述


网站公告

今日签到

点亮在社区的每一天
去签到