深度剖析bmp图像读入输出的方式

好的,话不多说,我们直接开始

图像处理在各个方面的应用都是十分广泛的,这里不再一一列举

但是图像处理的第一步永远是图像的读入

我们在本篇文章将会讲解读入的方式

如果你对图像处理很有兴趣但是这篇文章又没有从头去讲解,可以去阅读我之前的文章

图像处理与图像分析—图像的读入(C语言)_c语言读取各种图像的函数-CSDN博客


图像的规格

这里就绕不开一个关键词—图片位深度

什么是图片位深度呢?

位深度是指在记录数字图像的颜色时,计算机实际上是用每个像素需要的位深度来表示的。计算机之所以能够显示颜色,是采用了一种称作“位”( bit ) 的记数单位来记录所表示颜色的数据。当这些数据按照一定的编排方式被记录在计算机中,就构成了一个数字图像的计算机文件。**“位”( bit )是计算机存储器里的最小单元,它用来记录每一个像素颜色的值。图像的色彩越丰富,“位”就越多。**每一个像素在计算机中所使用的这种位数就是“位深度”。

术语很多,看起来并不是很好理解

我们接着往下看

黑白二色的图像是数字图像中最简单的一种,它只有黑、白两种颜色,也就是说它的每个像素只有1位颜色,位深度是1,用2的一次幂来表示;考虑到位深度平均分给R, G, B和Alpha,而只有RGB可以相互组合成颜色。所以4位颜色的图,它的位深度是4,只有2的4次幂种颜色,(即16种颜色或16种灰度等级 )。8位颜色的图,位深度就是8,用2的8次幂表示,它含有256种颜色 ( 或256种灰度等级 )。24位颜色可称之为真彩色,位深度是24,它能组合成2的24次幂种颜色,即:16777216种颜色 ( 或称千万种颜色 ),超过了人眼能够分辨的颜色数量。当我们用24位来记录颜色时,实际上是以2^(8×3),即红、绿、蓝 ( RGB ) 三基色各以2的8次幂,256种颜色而存在的,三色组合就形成一千六百万种颜色。

我们来总结一下,其实也很简单

位深度就是每一个像素块在计算机内存储的大小

只有黑白色

image-20240418194831461

那么我们怎么储存?

很简单,每一块像素之中0表示黑,1表示白

在计算机中一个bit就可以储存一个像素点

也就是一位图像

八位灰度图像

image-20240418195048709

这幅图就和上面的明显不同了,黑色有了深浅变化,那么从全黑到全白,我们一共分为256种不同深度的灰色,然后放在计算机中储存

那么每个像素块需要多大的储存空间呢?

没错,我们需要8个bit — 2的8次方刚好就等于256

这就是八位图像

二十四位图像

image-20240418200114430

彩色的米老鼠我就不用啦,这次用海绵宝宝举例子

其实我们在日常生活中见到的最多的图像都是彩色的图像,这些图像是怎么存储的呢?

我们绕不开一个概念—混色效应

image-20240418200717342

好的,在彩色图像的存储中,我们只需要每个像素存红绿蓝三个颜色的灰度值就行,那也就是说,每个像素要存三个八位灰度值,一共就是—24个bit

也就是24位的彩色图像


图像的读入

我们读取图像也会用8位图像和24位图像来读取

首先来看八位灰度图像


八位灰度图像的读入

先分析函数需求
  • 传入文件地址
  • 传入图像的长和宽
  • 返回图像的储存空间

先来看上次写的代码

int main()
{
    const char* filename = "E:/code/IDP-Learning-Journey/images/ME.bmp";

    FILE* file = fopen(filename, "rb");

    uint8_t bmpHeader[54];
    fread(bmpHeader, 1, 54, file);

    int width = *(int*)&bmpHeader[18];   // 宽度信息位于偏移量为 18 的位置
    int height = *(int*)&bmpHeader[22];  // 高度信息位于偏移量为 22 的位置

    uint8_t* imageData = (uint8_t*)malloc(width * height);  // 每个像素点占用 3 个字节(BGR)

    fseek(file, 54, SEEK_SET);  // 跳过 BMP 文件头

    fread(imageData, 1, width * height, file);  // 每个像素点占用 3 个字节(BGR)

    F1(imageData, width, height);

    fclose(file);
    free(imageData);

    return 0;
}

很草率但是也能达到需求,其实有很多地方可以继续优化,但是只能读取24位的数据

我们来写成函数读取8位灰度图像试试

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

uint8_t* readGrayScaleBMP(const char* filename, int* width, int* height) {
    FILE* file = fopen(filename, "rb");
    if (!file) {
        fprintf(stderr, "Error opening file %s\n", filename);
        return NULL;
    }

    // 读取BMP文件头部信息
    uint8_t bmpHeader[54];
    fread(bmpHeader, 1, 54, file);

    // 从文件头部提取图像宽度和高度信息
    *width = *(int*)&bmpHeader[18];
    *height = *(int*)&bmpHeader[22];

    // 分配存储图像数据的内存
    uint8_t* imageData = (uint8_t*)malloc(*width * *height);
    if (!imageData) {
        fprintf(stderr, "内存分配失败\n");
        fclose(file);
        return NULL;
    }

    // 计算调色板的大小
    int paletteSize = *(int*)&bmpHeader[46];
    if (paletteSize == 0)
        paletteSize = 256;

    // 读取调色板数据
    uint8_t palette[1024];
    fread(palette, 1, paletteSize * 4, file);

    // 读取图像数据
    fseek(file, *(int*)&bmpHeader[10], SEEK_SET);
    fread(imageData, 1, *width * *height, file);

    fclose(file);

    return imageData;
}

好的,这样一个函数应该就可以正常实现功能了

image-20240418215234113

我们来试一下功能,当然得写一个写入的函数


八位图像写入

直接上代码

// 将8位灰度图像数据保存为BMP文件
void saveGrayScaleBMP(const char* filename, const uint8_t* imageData, int width, int height) {
    FILE* file = fopen(filename, "wb");
    if (!file) {
        fprintf(stderr, "Error creating file %s\n", filename);
        return;
    }

    // BMP文件头部信息
    uint8_t bmpHeader[54] = {
        0x42, 0x4D,             // 文件类型标识 "BM"
        0x36, 0x00, 0x0C, 0x00, // 文件大小(以字节为单位,此处假设图像数据大小不超过4GB)
        0x00, 0x00,             // 保留字段
        0x00, 0x00,             // 保留字段
        0x36, 0x00, 0x00, 0x00, // 位图数据偏移(以字节为单位)
        0x28, 0x00, 0x00, 0x00, // 位图信息头大小(40字节)
        0x00, 0x00, 0x00, 0x00, // 图像宽度
        0x00, 0x00, 0x00, 0x00, // 图像高度
        0x01, 0x00,             // 目标设备的级别(此处为1,不压缩)
        0x08, 0x00,             // 每个像素的位数(8位)
        0x00, 0x00, 0x00, 0x00, // 压缩类型(此处为不压缩)
        0x00, 0x00, 0x00, 0x00, // 图像数据大小(以字节为单位,此处为0,表示不压缩)
        0x00, 0x00, 0x00, 0x00, // 水平分辨率(像素/米,此处为0,表示未知)
        0x00, 0x00, 0x00, 0x00, // 垂直分辨率(像素/米,此处为0,表示未知)
        0x00, 0x00, 0x00, 0x00, // 使用的颜色索引数(0表示使用所有调色板项)
        0x00, 0x00, 0x00, 0x00  // 重要的颜色索引数(0表示所有颜色都重要)
    };

    // 更新BMP文件头部信息中的宽度和高度
    *(int*)&bmpHeader[18] = width;
    *(int*)&bmpHeader[22] = height;

    // 写入BMP文件头部信息
    fwrite(bmpHeader, 1, 54, file);

    // 写入调色板数据
    for (int i = 0; i < 256; i++) {
        fputc(i, file);  // 蓝色分量
        fputc(i, file);  // 绿色分量
        fputc(i, file);  // 红色分量
        fputc(0, file);  // 保留字节
    }

    // 写入图像数据
    fwrite(imageData, 1, width * height, file);

    fclose(file);
}

那么带上之前的试一下效果

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

uint8_t* readGrayScaleBMP(const char* filename, int* width, int* height) {
    FILE* file = fopen(filename, "rb");
    if (!file) {
        fprintf(stderr, "Error opening file %s\n", filename);
        return NULL;
    }

    // 读取BMP文件头部信息
    uint8_t bmpHeader[54];
    fread(bmpHeader, 1, 54, file);

    // 从文件头部提取图像宽度和高度信息
    *width = *(int*)&bmpHeader[18];
    *height = *(int*)&bmpHeader[22];

    // 分配存储图像数据的内存
    uint8_t* imageData = (uint8_t*)malloc(*width * *height);
    if (!imageData) {
        fprintf(stderr, "内存分配失败\n");
        fclose(file);
        return NULL;
    }

    // 计算调色板的大小
    int paletteSize = *(int*)&bmpHeader[46];
    if (paletteSize == 0)
        paletteSize = 256;

    // 读取调色板数据
    uint8_t palette[1024];
    fread(palette, 1, paletteSize * 4, file);

    // 读取图像数据
    fseek(file, *(int*)&bmpHeader[10], SEEK_SET);
    fread(imageData, 1, *width * *height, file);

    fclose(file);

    return imageData;
}

// 将8位灰度图像数据保存为BMP文件
void saveGrayScaleBMP(const char* filename, const uint8_t* imageData, int width, int height) {
    FILE* file = fopen(filename, "wb");
    if (!file) {
        fprintf(stderr, "Error creating file %s\n", filename);
        return;
    }

    // BMP文件头部信息
    uint8_t bmpHeader[54] = {
        0x42, 0x4D,             // 文件类型标识 "BM"
        0x36, 0x00, 0x0C, 0x00, // 文件大小(以字节为单位,此处假设图像数据大小不超过4GB)
        0x00, 0x00,             // 保留字段
        0x00, 0x00,             // 保留字段
        0x36, 0x00, 0x00, 0x00, // 位图数据偏移(以字节为单位)
        0x28, 0x00, 0x00, 0x00, // 位图信息头大小(40字节)
        0x00, 0x00, 0x00, 0x00, // 图像宽度
        0x00, 0x00, 0x00, 0x00, // 图像高度
        0x01, 0x00,             // 目标设备的级别(此处为1,不压缩)
        0x08, 0x00,             // 每个像素的位数(8位)
        0x00, 0x00, 0x00, 0x00, // 压缩类型(此处为不压缩)
        0x00, 0x00, 0x00, 0x00, // 图像数据大小(以字节为单位,此处为0,表示不压缩)
        0x00, 0x00, 0x00, 0x00, // 水平分辨率(像素/米,此处为0,表示未知)
        0x00, 0x00, 0x00, 0x00, // 垂直分辨率(像素/米,此处为0,表示未知)
        0x00, 0x00, 0x00, 0x00, // 使用的颜色索引数(0表示使用所有调色板项)
        0x00, 0x00, 0x00, 0x00  // 重要的颜色索引数(0表示所有颜色都重要)
    };

    // 更新BMP文件头部信息中的宽度和高度
    *(int*)&bmpHeader[18] = width;
    *(int*)&bmpHeader[22] = height;

    // 写入BMP文件头部信息
    fwrite(bmpHeader, 1, 54, file);

    // 写入调色板数据
    for (int i = 0; i < 256; i++) {
        fputc(i, file);  // 蓝色分量
        fputc(i, file);  // 绿色分量
        fputc(i, file);  // 红色分量
        fputc(0, file);  // 保留字节
    }

    // 写入图像数据
    fwrite(imageData, 1, width * height, file);

    fclose(file);
}

int main() {
    const char* grayScaleFilename = "gray_scale.bmp";

    int grayScaleWidth, grayScaleHeight;

    // 读取8位灰度图像
    uint8_t* grayScaleImageData = readGrayScaleBMP(grayScaleFilename, &grayScaleWidth, &grayScaleHeight);
    if (!grayScaleImageData) {
        fprintf(stderr, "Failed to read gray scale BMP image\n");
        return 1;
    }

    // 执行对灰度图像的操作
    // 保存8位灰度图像数据为BMP文件
    saveGrayScaleBMP("out.bmp", grayScaleImageData, grayScaleWidth, grayScaleHeight);

    free(grayScaleImageData);


    return 0;
}

image-20240418215931015

好的,难得的成功,24位图像实际上是要比8位简单的


24位图像的读取

直接上代码

// 读取24位彩色图像的BMP文件
uint8_t* readColorBMP(const char* filename, int* width, int* height) {
    FILE* file = fopen(filename, "rb");
    if (!file) {
        fprintf(stderr, "Error opening file %s\n", filename);
        return NULL;
    }

    // 读取BMP文件头部信息
    uint8_t bmpHeader[54];
    fread(bmpHeader, 1, 54, file);

    // 从文件头部提取图像宽度和高度信息
    *width = *(int*)&bmpHeader[18];
    *height = *(int*)&bmpHeader[22];

    // 分配存储图像数据的内存
    uint8_t* imageData = (uint8_t*)malloc(*width * *height * 3);
    if (!imageData) {
        fprintf(stderr, "Memory allocation failed\n");
        fclose(file);
        return NULL;
    }

    // 读取图像数据
    fseek(file, *(int*)&bmpHeader[10], SEEK_SET);
    fread(imageData, 1, *width * *height * 3, file);

    fclose(file);

    return imageData;
}

这次连调色板都用不上,直接就可以读取

我们再来写一个写入函数看看效果


24位图像的写入

直接来写一个代码

void saveColorBMP(const char* filename, const uint8_t* imageData, int width, int height) {
    FILE* file = fopen(filename, "wb");
    if (!file) {
        fprintf(stderr, "Error creating file %s\n", filename);
        return;
    }

    // BMP文件头部信息
    uint8_t bmpHeader[54] = {
        0x42, 0x4D,             // 文件类型标识 "BM"
        0x00, 0x00, 0x00, 0x00, // 文件大小(占位,稍后计算)
        0x00, 0x00,             // 保留字段
        0x00, 0x00,             // 保留字段
        0x36, 0x00, 0x00, 0x00, // 位图数据偏移(以字节为单位)
        0x28, 0x00, 0x00, 0x00, // 位图信息头大小(40字节)
        0x00, 0x00, 0x00, 0x00, // 图像宽度
        0x00, 0x00, 0x00, 0x00, // 图像高度
        0x01, 0x00,             // 目标设备的级别(此处为1,不压缩)
        0x18, 0x00,             // 每个像素的位数(24位)
        0x00, 0x00, 0x00, 0x00, // 压缩类型(此处为不压缩)
        0x00, 0x00, 0x00, 0x00, // 图像数据大小(占位,稍后计算)
        0x00, 0x00, 0x00, 0x00, // 水平分辨率(像素/米,此处为0,表示未知)
        0x00, 0x00, 0x00, 0x00, // 垂直分辨率(像素/米,此处为0,表示未知)
        0x00, 0x00, 0x00, 0x00, // 使用的颜色索引数(0表示使用所有调色板项)
        0x00, 0x00, 0x00, 0x00  // 重要的颜色索引数(0表示所有颜色都重要)
    };

    // 更新BMP文件头部信息中的宽度和高度
    *(int*)&bmpHeader[18] = width;
    *(int*)&bmpHeader[22] = height;

    // 计算图像数据大小
    uint32_t imageDataSize = width * height * 3 + 54; // 加上文件头部大小
    bmpHeader[2] = (uint8_t)(imageDataSize & 0xFF);
    bmpHeader[3] = (uint8_t)((imageDataSize >> 8) & 0xFF);
    bmpHeader[4] = (uint8_t)((imageDataSize >> 16) & 0xFF);
    bmpHeader[5] = (uint8_t)((imageDataSize >> 24) & 0xFF);

    // 写入BMP文件头部信息
    fwrite(bmpHeader, 1, 54, file);

    // 写入图像数据
    fwrite(imageData, width * height * 3, 1, file);

    fclose(file);
}

image-20240418221259833

我们来看看实现效果

image-20240418222226376

再次修改尝试

image-20240418225312059

经过测试,只有这张图片不行,目前还没有找到原因

image-20240418232809410


总结

好的,那么我们这次介绍了图像的读取和写入

是图像处理的基础

出现的问题找到原因后会及时更新博客

感谢大家的阅读

源码

#define _CRT_SECURE_NO_WARNINGS 1

#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

uint8_t* readGrayScaleBMP(const char* filename, int* width, int* height) {
    FILE* file = fopen(filename, "rb");
    if (!file) {
        fprintf(stderr, "Error opening file %s\n", filename);
        return NULL;
    }

    // 读取BMP文件头部信息
    uint8_t bmpHeader[54];
    fread(bmpHeader, 1, 54, file);

    // 从文件头部提取图像宽度和高度信息
    *width = *(int*)&bmpHeader[18];
    *height = *(int*)&bmpHeader[22];

    // 分配存储图像数据的内存
    uint8_t* imageData = (uint8_t*)malloc(*width * *height);
    if (!imageData) {
        fprintf(stderr, "内存分配失败\n");
        fclose(file);
        return NULL;
    }

    // 计算调色板的大小
    int paletteSize = *(int*)&bmpHeader[46];
    if (paletteSize == 0)
        paletteSize = 256;

    // 读取调色板数据
    uint8_t palette[1024];
    fread(palette, 1, paletteSize * 4, file);

    // 读取图像数据
    fseek(file, *(int*)&bmpHeader[10], SEEK_SET);
    fread(imageData, 1, *width * *height, file);

    fclose(file);

    return imageData;
}

// 将8位灰度图像数据保存为BMP文件
void saveGrayScaleBMP(const char* filename, const uint8_t* imageData, int width, int height) {
    FILE* file = fopen(filename, "wb");
    if (!file) {
        fprintf(stderr, "Error creating file %s\n", filename);
        return;
    }

    // BMP文件头部信息
    uint8_t bmpHeader[54] = {
        0x42, 0x4D,             // 文件类型标识 "BM"
        0x36, 0x00, 0x0C, 0x00, // 文件大小(以字节为单位,此处假设图像数据大小不超过4GB)
        0x00, 0x00,             // 保留字段
        0x00, 0x00,             // 保留字段
        0x36, 0x00, 0x00, 0x00, // 位图数据偏移(以字节为单位)
        0x28, 0x00, 0x00, 0x00, // 位图信息头大小(40字节)
        0x00, 0x00, 0x00, 0x00, // 图像宽度
        0x00, 0x00, 0x00, 0x00, // 图像高度
        0x01, 0x00,             // 目标设备的级别(此处为1,不压缩)
        0x08, 0x00,             // 每个像素的位数(8位)
        0x00, 0x00, 0x00, 0x00, // 压缩类型(此处为不压缩)
        0x00, 0x00, 0x00, 0x00, // 图像数据大小(以字节为单位,此处为0,表示不压缩)
        0x00, 0x00, 0x00, 0x00, // 水平分辨率(像素/米,此处为0,表示未知)
        0x00, 0x00, 0x00, 0x00, // 垂直分辨率(像素/米,此处为0,表示未知)
        0x00, 0x00, 0x00, 0x00, // 使用的颜色索引数(0表示使用所有调色板项)
        0x00, 0x00, 0x00, 0x00  // 重要的颜色索引数(0表示所有颜色都重要)
    };

    // 更新BMP文件头部信息中的宽度和高度
    *(int*)&bmpHeader[18] = width;
    *(int*)&bmpHeader[22] = height;

    // 写入BMP文件头部信息
    fwrite(bmpHeader, 1, 54, file);

    // 写入调色板数据
    for (int i = 0; i < 256; i++) {
        fputc(i, file);  // 蓝色分量
        fputc(i, file);  // 绿色分量
        fputc(i, file);  // 红色分量
        fputc(0, file);  // 保留字节
    }

    // 写入图像数据
    fwrite(imageData, 1, width * height, file);

    fclose(file);
}

// 读取24位彩色图像的BMP文件
uint8_t* readColorBMP(const char* filename, int* width, int* height) {
    FILE* file = fopen(filename, "rb");
    if (!file) {
        fprintf(stderr, "Error opening file %s\n", filename);
        return NULL;
    }

    // 读取BMP文件头部信息
    uint8_t bmpHeader[54];
    fread(bmpHeader, 1, 54, file);

    // 从文件头部提取图像宽度和高度信息
    *width = *(int*)&bmpHeader[18];
    *height = *(int*)&bmpHeader[22];

    // 分配存储图像数据的内存
    uint8_t* imageData = (uint8_t*)malloc(*width * *height * 3);
    if (!imageData) {
        fprintf(stderr, "Memory allocation failed\n");
        fclose(file);
        return NULL;
    }

    // 读取图像数据
    fseek(file, *(int*)&bmpHeader[10], SEEK_SET);
    fread(imageData, 1, *width * *height * 3, file);

    fclose(file);

    return imageData;
}

void saveColorBMP(const char* filename, const uint8_t* imageData, int width, int height) {
    FILE* file = fopen(filename, "wb");
    if (!file) {
        fprintf(stderr, "Error creating file %s\n", filename);
        return;
    }

    // BMP文件头部信息
    uint8_t bmpHeader[54] = {
        0x42, 0x4D,             // 文件类型标识 "BM"
        0x00, 0x00, 0x00, 0x00, // 文件大小(占位,稍后计算)
        0x00, 0x00,             // 保留字段
        0x00, 0x00,             // 保留字段
        0x36, 0x00, 0x00, 0x00, // 位图数据偏移(以字节为单位)
        0x28, 0x00, 0x00, 0x00, // 位图信息头大小(40字节)
        0x00, 0x00, 0x00, 0x00, // 图像宽度
        0x00, 0x00, 0x00, 0x00, // 图像高度
        0x01, 0x00,             // 目标设备的级别(此处为1,不压缩)
        0x18, 0x00,             // 每个像素的位数(24位)
        0x00, 0x00, 0x00, 0x00, // 压缩类型(此处为不压缩)
        0x00, 0x00, 0x00, 0x00, // 图像数据大小(占位,稍后计算)
        0x00, 0x00, 0x00, 0x00, // 水平分辨率(像素/米,此处为0,表示未知)
        0x00, 0x00, 0x00, 0x00, // 垂直分辨率(像素/米,此处为0,表示未知)
        0x00, 0x00, 0x00, 0x00, // 使用的颜色索引数(0表示使用所有调色板项)
        0x00, 0x00, 0x00, 0x00  // 重要的颜色索引数(0表示所有颜色都重要)
    };

    // 更新BMP文件头部信息中的宽度和高度
    *(int*)&bmpHeader[18] = width;
    *(int*)&bmpHeader[22] = height;

    // 计算图像数据大小
    uint32_t imageDataSize = width * height * 3 + 54; // 加上文件头部大小
    bmpHeader[2] = (uint8_t)(imageDataSize & 0xFF);
    bmpHeader[3] = (uint8_t)((imageDataSize >> 8) & 0xFF);
    bmpHeader[4] = (uint8_t)((imageDataSize >> 16) & 0xFF);
    bmpHeader[5] = (uint8_t)((imageDataSize >> 24) & 0xFF);

    // 写入BMP文件头部信息
    fwrite(bmpHeader, 1, 54, file);

    // 写入图像数据
    fwrite(imageData, width * height * 3, 1, file);

    fclose(file);
}


int main() {
    const char* grayScaleFilename = "gray_scale.bmp";
    const char* colorFilename = "FXT12111.bmp";

    int grayScaleWidth, grayScaleHeight;
    int width, height;

    // 读取8位灰度图像
    uint8_t* grayScaleImageData = readGrayScaleBMP(grayScaleFilename, &grayScaleWidth, &grayScaleHeight);
    if (!grayScaleImageData) {
        fprintf(stderr, "Failed to read gray scale BMP image\n");
        return 1;
    }

    // 读取24位彩色图像
    uint8_t* colorImageData = readColorBMP(colorFilename, &width, &height);
    if (!colorImageData) {
        fprintf(stderr, "Failed to read color BMP image\n");
        return 1;
    }

    // 执行对灰度图像的操作
    // 保存8位灰度图像数据为BMP文件
    saveGrayScaleBMP("out.bmp", grayScaleImageData, grayScaleWidth, grayScaleHeight);

    // 保存24位灰度图像数据为BMP文件
    saveColorBMP("outcolor.bmp", colorImageData, width, height);
    

    free(grayScaleImageData);
    free(colorImageData);


    return 0;
}
  • 46
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
下面是一个简单的 C 语言示例程序,用于从 BMP 文件中读取图像数据: ```c #include <stdio.h> #include <stdlib.h> #include <stdint.h> #pragma pack(push, 1) typedef struct { uint16_t type; uint32_t size; uint16_t reserved1; uint16_t reserved2; uint32_t offset; } bmp_file_header_t; typedef struct { uint32_t size; int32_t width; int32_t height; uint16_t planes; uint16_t bit_count; uint32_t compression; uint32_t size_image; int32_t x_pels_per_meter; int32_t y_pels_per_meter; uint32_t clr_used; uint32_t clr_important; } bmp_info_header_t; #pragma pack(pop) int main(int argc, char *argv[]) { if (argc != 2) { printf("Usage: %s input.bmp\n", argv[0]); return 0; } FILE *input_file = fopen(argv[1], "rb"); if (!input_file) { printf("Failed to open input file: %s\n", argv[1]); return 0; } bmp_file_header_t file_header; bmp_info_header_t info_header; fread(&file_header, sizeof(bmp_file_header_t), 1, input_file); fread(&info_header, sizeof(bmp_info_header_t), 1, input_file); if (file_header.type != 0x4d42 || info_header.bit_count != 24 || info_header.compression != 0) { printf("Invalid input file format.\n"); fclose(input_file); return 0; } uint32_t width = abs(info_header.width); uint32_t height = abs(info_header.height); uint32_t line_size = (width * 3 + 3) & ~3; uint8_t *image_data = (uint8_t *)malloc(line_size * height); fseek(input_file, file_header.offset, SEEK_SET); fread(image_data, line_size, height, input_file); fclose(input_file); // 现在 image_data 中存储了 BMP 文件中的像素数据,可以进行进一步处理 free(image_data); printf("Done.\n"); return 0; } ``` 在这个示例代码中,我们使用了两个结构体来解析 BMP 文件头和信息头的数据。首先,我们打开 BMP 文件并读取文件头和信息头。然后,我们检查文件头和信息头是否符合要求(即文件类型必须是 "BM",颜色位数必须是 24 位,不支持压缩)。接下来,我们计算每一行像素数据的字节数,使用 malloc 函数分配足够的内存来存储像素数据,并使用 fread 函数从文件中读取像素数据。最后,我们关闭文件,并使用 free 函数释放内存。 请注意,这个示例代码只适用于 24 位彩色 BMP 图片。如果你想处理其他格式的 BMP 图片,需要根据实际情况进行修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

J.Pei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值