欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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:
BMP文件学习笔记(二):将BMP格式RGB真彩色图片转换成灰度图片
运行程序后,转换成的灰度图片gray.bmp:
BMP文件学习笔记(二):将BMP格式RGB真彩色图片转换成灰度图片