BMP文件学习笔记(二):将BMP格式RGB真彩色图片转换成灰度图片

来源:互联网 发布:网络批发干货平台 编辑:程序博客网 时间:2024/05/18 03:10

1 准备知识

关于BMP文件知识可参见上篇:《BMP文件学习笔记(一): C/C++语言实现.bmp文件读写》,或者自行搜索查阅更详细的介绍。
RGB图片转换成灰度图片,有公式:Gray = r*0.299 + g*0.587 + b*0.114
下面的程序也是按这个公式来写的。

2 编程

代码如下:
#include <stdio.h>#include <Windows.h>void rgb2gray(char * rgbflie, char * grayflie){FILE * prgbfile, * pgrayfile;prgbfile = fopen(rgbflie, "rb");pgrayfile = fopen(grayflie, "wb");if (NULL == prgbfile || NULL == pgrayfile){printf("文件打开失败!\n");fclose(prgbfile);fclose(pgrayfile);return;}BITMAPFILEHEADER bitMapFileHeader_rgb, bitMapFileHeader_gray;fread(&bitMapFileHeader_rgb, sizeof(BITMAPFILEHEADER), 1, prgbfile);if (0x4D42 != bitMapFileHeader_rgb.bfType){printf("源文件不是BMP文件!\n");return ;}BITMAPINFOHEADER bitMapInfoHeader_rgb, bitMapInfoHeader_gray;fread(&bitMapInfoHeader_rgb, sizeof(BITMAPINFOHEADER), 1, prgbfile);if (24 != bitMapInfoHeader_rgb.biBitCount){printf("源文件不是RGB彩色图片!\n");return;}int width = bitMapInfoHeader_rgb.biWidth;int height = bitMapInfoHeader_rgb.biHeight;int bitCount = bitMapInfoHeader_rgb.biBitCount;//图像数据每行字节数为4的倍数int lineByte_rgb = (width * bitCount / 8 + 3) / 4 * 4; //RGB图unsigned char * pData = new unsigned char[lineByte_rgb * height];fread(pData, sizeof(unsigned char), lineByte_rgb * height, prgbfile);int lineByte_gray = (width * 8 / 8 + 3) / 4 * 4; //灰度图bitMapFileHeader_gray.bfType = 0x4D42;bitMapFileHeader_gray.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 1024 + lineByte_gray * height;bitMapFileHeader_gray.bfReserved1 = 0;bitMapFileHeader_gray.bfReserved2 = 0;bitMapFileHeader_gray.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 1024;bitMapInfoHeader_gray.biBitCount = 8;bitMapInfoHeader_gray.biClrImportant = 0;bitMapInfoHeader_gray.biClrUsed = 0;bitMapInfoHeader_gray.biCompression = 0;bitMapInfoHeader_gray.biHeight = height;bitMapInfoHeader_gray.biPlanes = 1;bitMapInfoHeader_gray.biSize = 40;bitMapInfoHeader_gray.biSizeImage = lineByte_gray * height;bitMapInfoHeader_gray.biWidth = width;bitMapInfoHeader_gray.biXPelsPerMeter = 0;bitMapInfoHeader_gray.biYPelsPerMeter = 0;//调色板RGBQUAD * pRGBQUAD = new RGBQUAD[256];for (int i = 0; i<256; i++){pRGBQUAD[i].rgbBlue = i;pRGBQUAD[i].rgbGreen = i;pRGBQUAD[i].rgbRed = i;pRGBQUAD[i].rgbReserved = 0;}//写文件头进文件fwrite(&bitMapFileHeader_gray, sizeof(BITMAPFILEHEADER), 1, pgrayfile);//写位图信息头进内存fwrite(&bitMapInfoHeader_gray, sizeof(BITMAPINFOHEADER), 1, pgrayfile);//写调色板进文件 fwrite(pRGBQUAD, sizeof(RGBQUAD), 256, pgrayfile);//写数据进文for (int i = 0; i < height; i++){for (int j = 0; j < lineByte_gray; j++){//公式:Gray = r*0.299 + g*0.587 + b*0.114unsigned char bVal = *(pData + lineByte_rgb * i + 3 * j);unsigned char gVal = *(pData + lineByte_rgb * i + 3 * j + 1);unsigned char rVal = *(pData + lineByte_rgb * i + 3 * j + 2);unsigned char grayVal = bVal * 0.114 + gVal * 0.587 + rVal * 0.299;fwrite(&grayVal, sizeof(unsigned char), 1, pgrayfile);}}fclose(prgbfile);fclose(pgrayfile);delete[] pData;pData = NULL;}int main(){char * rgbflie = "rgb.bmp";char * grayflie = "gray.bmp";rgb2gray(rgbflie, grayflie);return 0;}

3 效果

源始RGB图片rgb.bmp:

运行程序后,转换成的灰度图片gray.bmp: