BMP文件学习笔记(二):将BMP格式RGB真彩色图片转换成灰度图片
程序员文章站
2022-05-21 23:53:25
...
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.114
unsigned 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: