问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

如何用C语言编辑BMP文件

创作时间:
作者:
@小白创作中心

如何用C语言编辑BMP文件

引用
1
来源
1.
https://docs.pingcode.com/baike/1231064


如何用C语言编辑BMP文件学习BMP文件格式、熟悉C语言文件处理函数、处理像素数据。BMP文件是一种位图图像格式,广泛用于存储图像。要用C语言编辑BMP文件,首先需要理解BMP文件格式,其次要掌握C语言中的文件处理函数,最后还要能够处理和修改图像的像素数据。接下来,我们将详细探讨这些步骤。

一、BMP文件格式

BMP文件格式非常简单,是一种无压缩的图像存储格式。它由文件头、信息头、颜色表(可选)和像素数据四部分组成。

1、文件头(BITMAPFILEHEADER)

文件头包含文件的基本信息,如文件大小、保留字段、实际图像数据的偏移量等。

typedef struct {  
    unsigned short bfType;      // 文件类型,必须是BM  
    unsigned int bfSize;        // 文件大小,以字节为单位  
    unsigned short bfReserved1; // 保留,必须设置为0  
    unsigned short bfReserved2; // 保留,必须设置为0  
    unsigned int bfOffBits;     // 图像数据的偏移量  
} BITMAPFILEHEADER;  

2、信息头(BITMAPINFOHEADER)

信息头包含图像的详细信息,如宽度、高度、色深等。

typedef struct {  
    unsigned int biSize;          // 信息头大小  
    int biWidth;                  // 图像宽度  
    int biHeight;                 // 图像高度  
    unsigned short biPlanes;      // 颜色平面数,必须设置为1  
    unsigned short biBitCount;    // 每像素位数  
    unsigned int biCompression;   // 压缩类型  
    unsigned int biSizeImage;     // 图像大小  
    int biXPelsPerMeter;          // 水平分辨率  
    int biYPelsPerMeter;          // 垂直分辨率  
    unsigned int biClrUsed;       // 使用的颜色数  
    unsigned int biClrImportant;  // 重要颜色数  
} BITMAPINFOHEADER;  

3、颜色表

颜色表只在8位或更少颜色深度的BMP文件中存在,定义了图像中使用的颜色。

4、像素数据

像素数据是图像的实际数据,按行存储,每行的长度必须是4的倍数。

二、C语言文件处理函数

要操作BMP文件,需要使用C语言的文件处理函数,如
fopen

fread

fwrite

fseek
等。

1、打开文件

使用
fopen
函数打开文件。

FILE *file = fopen("image.bmp", "rb+");  
if (!file) {  
    printf("Cannot open filen");  
    return;  
}  

2、读取文件头和信息头

使用
fread
函数读取文件头和信息头。

BITMAPFILEHEADER fileHeader;  
BITMAPINFOHEADER infoHeader;  
fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, file);  
fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, file);  

3、读取像素数据

根据文件头中的偏移量,读取像素数据。

fseek(file, fileHeader.bfOffBits, SEEK_SET);  
int imageSize = infoHeader.biWidth * infoHeader.biHeight * (infoHeader.biBitCount / 8);  
unsigned char *imageData = (unsigned char *)malloc(imageSize);  
fread(imageData, imageSize, 1, file);  

4、修改像素数据

可以根据需要修改像素数据,例如将图像转换为灰度图像。

for (int i = 0; i < imageSize; i += 3) {  
    unsigned char gray = (imageData[i] + imageData[i + 1] + imageData[i + 2]) / 3;  
    imageData[i] = imageData[i + 1] = imageData[i + 2] = gray;  
}  

5、写回文件

将修改后的像素数据写回文件。

fseek(file, fileHeader.bfOffBits, SEEK_SET);  
fwrite(imageData, imageSize, 1, file);  

6、关闭文件

最后,关闭文件并释放内存。

fclose(file);  
free(imageData);  

三、处理像素数据

处理像素数据是编辑BMP文件的核心步骤。可以进行各种操作,如调整亮度、对比度、旋转、缩放等。

1、调整亮度

通过增加或减少每个像素的RGB值来调整亮度。

void adjustBrightness(unsigned char *imageData, int imageSize, int adjustment) {  
    for (int i = 0; i < imageSize; i++) {  
        int temp = imageData[i] + adjustment;  
        imageData[i] = temp > 255 ? 255 : (temp < 0 ? 0 : temp);  
    }  
}  

2、调整对比度

通过增加或减少每个像素的RGB值与128的差值来调整对比度。

void adjustContrast(unsigned char *imageData, int imageSize, float factor) {  
    for (int i = 0; i < imageSize; i++) {  
        int temp = (int)((imageData[i] - 128) * factor + 128);  
        imageData[i] = temp > 255 ? 255 : (temp < 0 ? 0 : temp);  
    }  
}  

3、图像旋转

通过重新排列像素数据来实现图像旋转。

void rotateImage(unsigned char *imageData, unsigned char *rotatedData, int width, int height, int bitCount) {  
    int bytesPerPixel = bitCount / 8;  
    for (int y = 0; y < height; y++) {  
        for (int x = 0; x < width; x++) {  
            int srcIndex = (y * width + x) * bytesPerPixel;  
            int dstIndex = ((width - x - 1) * height + y) * bytesPerPixel;  
            for (int b = 0; b < bytesPerPixel; b++) {  
                rotatedData[dstIndex + b] = imageData[srcIndex + b];  
            }  
        }  
    }  
}  

四、应用示例

1、读取BMP文件并转换为灰度图像

#include <stdio.h>  
#include <stdlib.h>  
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;  
void convertToGrayscale(unsigned char *imageData, int imageSize) {  
    for (int i = 0; i < imageSize; i += 3) {  
        unsigned char gray = (imageData[i] + imageData[i + 1] + imageData[i + 2]) / 3;  
        imageData[i] = imageData[i + 1] = imageData[i + 2] = gray;  
    }  
}  
int main() {  
    FILE *file = fopen("input.bmp", "rb+");  
    if (!file) {  
        printf("Cannot open filen");  
        return 1;  
    }  
    BITMAPFILEHEADER fileHeader;  
    BITMAPINFOHEADER infoHeader;  
    fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, file);  
    fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, file);  
    fseek(file, fileHeader.bfOffBits, SEEK_SET);  
    int imageSize = infoHeader.biWidth * infoHeader.biHeight * (infoHeader.biBitCount / 8);  
    unsigned char *imageData = (unsigned char *)malloc(imageSize);  
    fread(imageData, imageSize, 1, file);  
    convertToGrayscale(imageData, imageSize);  
    fseek(file, fileHeader.bfOffBits, SEEK_SET);  
    fwrite(imageData, imageSize, 1, file);  
    fclose(file);  
    free(imageData);  
    return 0;  
}  

2、读取BMP文件并调整亮度

#include <stdio.h>  
#include <stdlib.h>  
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;  
void adjustBrightness(unsigned char *imageData, int imageSize, int adjustment) {  
    for (int i = 0; i < imageSize; i++) {  
        int temp = imageData[i] + adjustment;  
        imageData[i] = temp > 255 ? 255 : (temp < 0 ? 0 : temp);  
    }  
}  
int main() {  
    FILE *file = fopen("input.bmp", "rb+");  
    if (!file) {  
        printf("Cannot open filen");  
        return 1;  
    }  
    BITMAPFILEHEADER fileHeader;  
    BITMAPINFOHEADER infoHeader;  
    fread(&fileHeader, sizeof(BITMAPFILEHEADER), 1, file);  
    fread(&infoHeader, sizeof(BITMAPINFOHEADER), 1, file);  
    fseek(file, fileHeader.bfOffBits, SEEK_SET);  
    int imageSize = infoHeader.biWidth * infoHeader.biHeight * (infoHeader.biBitCount / 8);  
    unsigned char *imageData = (unsigned char *)malloc(imageSize);  
    fread(imageData, imageSize, 1, file);  
    adjustBrightness(imageData, imageSize, 50);  
    fseek(file, fileHeader.bfOffBits, SEEK_SET);  
    fwrite(imageData, imageSize, 1, file);  
    fclose(file);  
    free(imageData);  
    return 0;  
}  

五、总结

通过C语言编辑BMP文件需要理解BMP文件格式,熟悉C语言的文件处理函数,并能够处理和修改像素数据。本文详细介绍了如何读取和修改BMP文件的各个步骤,并提供了具体的代码示例。希望这些内容能够帮助你更好地理解和掌握用C语言编辑BMP文件的技巧。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号