如何用C语言编辑BMP文件
如何用C语言编辑BMP文件
如何用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文件的技巧。