c语言代码实现位图直方图均衡,编写一个程序,完成指定文件的直方图均衡,并存储到新文件,file1.bmp file2.bmp
时间: 2024-03-08 09:49:15 浏览: 57
好的,下面是实现代码:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma pack(push, 1)
typedef struct {
unsigned short bfType; // 位图文件的类型,必须为BM
unsigned int bfSize; // 位图文件的大小,以字节为单位
unsigned short bfReserved1; // 位图文件保留字,必须为0
unsigned short bfReserved2; // 位图文件保留字,必须为0
unsigned int bfOffBits; // 位图数据的起始位置,以相对于位图文件头的偏移量表示,以字节为单位
} BITMAPFILEHEADER;
typedef struct {
unsigned int biSize; // 本结构所占用字节数
int biWidth; // 位图的宽度,以像素为单位
int biHeight; // 位图的高度,以像素为单位
unsigned short biPlanes; // 目标设备的级别,必须为1
unsigned short biBitCount; // 每个像素所需的位数,必须是1、4、8或24
unsigned int biCompression; // 位图压缩类型,必须是0(不压缩)、1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)
unsigned int biSizeImage; // 位图的大小,以字节为单位
int biXPelsPerMeter; // 位图水平分辨率,每米像素数
int biYPelsPerMeter; // 位图垂直分辨率,每米像素数
unsigned int biClrUsed; // 位图实际使用的颜色表中的颜色数
unsigned int biClrImportant; // 位图显示过程中重要的颜色数
} BITMAPINFOHEADER;
#pragma pack(pop)
typedef struct {
unsigned char b, g, r;
} RGB;
// 计算直方图
void calc_histogram(unsigned char *data, int width, int height, int *hist) {
memset(hist, 0, sizeof(int) * 256);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
hist[data[i * width + j]]++;
}
}
}
// 直方图均衡
void histogram_equalization(unsigned char *src, int width, int height, unsigned char *dst) {
int hist[256];
calc_histogram(src, width, height, hist);
int cum_hist[256];
for (int i = 0; i < 256; i++) {
if (i == 0) {
cum_hist[i] = hist[i];
} else {
cum_hist[i] = cum_hist[i - 1] + hist[i];
}
}
int max_val = width * height;
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int val = src[i * width + j];
dst[i * width + j] = (unsigned char)(cum_hist[val] * 255 / max_val);
}
}
}
// 读取位图文件
RGB *read_bitmap(const char *filename, int *width, int *height) {
FILE *fp = fopen(filename, "rb");
if (!fp) {
return NULL;
}
BITMAPFILEHEADER fh;
BITMAPINFOHEADER ih;
fread(&fh, sizeof(BITMAPFILEHEADER), 1, fp);
fread(&ih, sizeof(BITMAPINFOHEADER), 1, fp);
*width = ih.biWidth;
*height = ih.biHeight;
int line_bytes = ((*width * ih.biBitCount + 31) / 32) * 4;
RGB *data = (RGB *)malloc(line_bytes * (*height));
fseek(fp, fh.bfOffBits, SEEK_SET);
for (int i = 0; i < *height; i++) {
fread(&data[(i * line_bytes) / 3], sizeof(RGB), *width, fp);
fseek(fp, line_bytes - (*width * 3), SEEK_CUR);
}
fclose(fp);
return data;
}
// 写入位图文件
void write_bitmap(const char *filename, RGB *data, int width, int height) {
FILE *fp = fopen(filename, "wb");
if (!fp) {
return;
}
int line_bytes = ((width * 24 + 31) / 32) * 4;
BITMAPFILEHEADER fh = { 'B' + ('M' << 8), line_bytes * height + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER), 0, 0, sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) };
BITMAPINFOHEADER ih = { sizeof(BITMAPINFOHEADER), width, height, 1, 24, 0, line_bytes * height, 0, 0, 0, 0 };
fwrite(&fh, sizeof(BITMAPFILEHEADER), 1, fp);
fwrite(&ih, sizeof(BITMAPINFOHEADER), 1, fp);
for (int i = 0; i < height; i++) {
fwrite(&data[(height - i - 1) * width], sizeof(RGB), width, fp);
fwrite("\0\0\0", 1, line_bytes - width * 3, fp);
}
fclose(fp);
}
int main() {
int width, height;
RGB *data = read_bitmap("file1.bmp", &width, &height);
unsigned char *gray_data = (unsigned char *)malloc(width * height);
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
RGB *pixel = &data[i * width + j];
gray_data[i * width + j] = (unsigned char)(0.299 * pixel->r + 0.587 * pixel->g + 0.114 * pixel->b);
}
}
unsigned char *eq_data = (unsigned char *)malloc(width * height);
histogram_equalization(gray_data, width, height, eq_data);
RGB *eq_rgb_data = (RGB *)malloc(width * height * sizeof(RGB));
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
unsigned char val = eq_data[i * width + j];
eq_rgb_data[i * width + j].r = val;
eq_rgb_data[i * width + j].g = val;
eq_rgb_data[i * width + j].b = val;
}
}
write_bitmap("file2.bmp", eq_rgb_data, width, height);
free(data);
free(gray_data);
free(eq_data);
free(eq_rgb_data);
return 0;
}
```
这个程序会读取指定的位图文件,将其转换为灰度图像,然后进行直方图均衡,最后将均衡后的图像存储到新文件中。程序中使用的是 24 位真彩色位图,如果需要处理其他格式的位图,需要修改代码中写入和读取位图的部分。
阅读全文