C++实现256x256 BMP图像直方图均衡化

本文将介绍如何使用C++和fread()fwrite()函数实现对大小为256x256、24位真彩的BMP格式图像进行直方图均衡化操作。

代码示例

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

#pragma pack(2) // 按2字节对齐

// bmp文件头
typedef struct {
    unsigned short bfType;
    unsigned int bfSize;
    unsigned short bfReserved1;
    unsigned short bfReserved2;
    unsigned int bfOffBits;
} BMPFILEHEADER;

// bmp信息头
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;
} BMPINFOHEADER;

int main() {
    FILE* fpIn = fopen('3.bmp', 'rb'); // 以二进制只读方式打开输入文件
    FILE* fpOut = fopen('4.bmp', 'wb'); // 以二进制写入方式打开输出文件

    if (fpIn == NULL || fpOut == NULL) {
        printf('Error: cannot open file!\n');
        return -1;
    }

    // 读取bmp文件头
    BMPFILEHEADER fileHeader;
    fread(&fileHeader, sizeof(BMPFILEHEADER), 1, fpIn);

    // 读取bmp信息头
    BMPINFOHEADER infoHeader;
    fread(&infoHeader, sizeof(BMPINFOHEADER), 1, fpIn);

    // 检查是否为24位真彩色图像
    if (infoHeader.biBitCount != 24) {
        printf('Error: not a 24-bit true color image!\n');
        return -1;
    }

    // 计算图像数据的大小
    int width = infoHeader.biWidth;
    int height = infoHeader.biHeight;
    int lineBytes = (width * 24 + 31) / 32 * 4; // 每行字节数,必须是4的倍数
    int imageSize = lineBytes * height; // 图像数据大小

    // 读取调色板
    unsigned char* palette = NULL;
    if (infoHeader.biClrUsed > 0) {
        palette = (unsigned char*)malloc(infoHeader.biClrUsed * 4);
        fread(palette, 4, infoHeader.biClrUsed, fpIn);
    }

    // 读取图像数据
    unsigned char* imageData = (unsigned char*)malloc(imageSize);
    fread(imageData, 1, imageSize, fpIn);

    // 计算R分量的直方图
    int hist[256] = {0};
    for (int i = 0; i < width * height; i++) {
        hist[imageData[i * 3 + 2]]++;
    }

    // 计算R分量的累积直方图
    int cumHist[256] = {0};
    cumHist[0] = hist[0];
    for (int i = 1; i < 256; i++) {
        cumHist[i] = cumHist[i - 1] + hist[i];
    }

    // 计算R分量的映射表
    unsigned char map[256];
    for (int i = 0; i < 256; i++) {
        map[i] = (unsigned char)(cumHist[i] * 255.0 / (width * height) + 0.5);
    }

    // 对R分量进行直方图均衡
    for (int i = 0; i < width * height; i++) {
        imageData[i * 3 + 2] = map[imageData[i * 3 + 2]];
    }

    // 写入bmp文件头
    fwrite(&fileHeader, sizeof(BMPFILEHEADER), 1, fpOut);
    fwrite(&infoHeader, sizeof(BMPINFOHEADER), 1, fpOut);

    // 写入调色板
    if (infoHeader.biClrUsed > 0) {
        fwrite(palette, 4, infoHeader.biClrUsed, fpOut);
    }

    // 写入图像数据
    fwrite(imageData, 1, imageSize, fpOut);

    // 释放内存
    if (palette != NULL) {
        free(palette);
    }
    free(imageData);

    // 关闭文件
    fclose(fpIn);
    fclose(fpOut);

    return 0;
}

代码解析

  1. 文件操作:

    • 使用fopen()函数以二进制模式打开输入文件('3.bmp')和输出文件('4.bmp')。
    • 使用fread()函数读取BMP文件头和信息头,并使用fwrite()函数写入修改后的文件头和信息头到输出文件。
    • 使用fread()读取图像数据,并使用fwrite()写入处理后的图像数据到输出文件。
  2. 数据结构:

    • 定义了BMPFILEHEADERBMPINFOHEADER结构体,分别用于存储BMP文件头和信息头数据。
  3. 图像数据处理:

    • 检查图像是否为24位真彩色图像。
    • 计算图像数据的大小,并使用malloc()分配内存空间来存储图像数据。
    • 计算R分量的直方图和累积直方图。
    • 计算R分量的映射表,用于将每个像素的R分量映射到均衡后的值。
    • 对R分量进行直方图均衡化,并将处理后的图像数据写入输出文件。
  4. 内存释放:

    • 使用free()释放动态分配的内存空间。

注意细节

  • 使用#pragma pack(2)指令按2字节对齐,避免读取文件头和信息头时出现错误。
  • 24位真彩色图像的每个像素由3个字节组成,分别表示R、G、B三个分量,在读取和处理图像数据时要注意。
  • 每行字节数必须是4的倍数,因此计算图像数据大小时需要使用公式lineBytes = (width * 24 + 31) / 32 * 4
  • 写入文件头和信息头时要保持与读取时的顺序和格式一致。
  • 确保将处理后的数据写入输出文件。

总结

本文详细介绍了如何使用C++和fread()fwrite()函数实现对大小为256x256、24位真彩的BMP格式图像进行直方图均衡化操作。代码示例可以作为参考,读者可以根据需要进行修改和扩展。

C++实现256x256 BMP图像直方图均衡化

原文地址: https://www.cveoy.top/t/topic/jCVq 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录