把24位和32位BMP位图转为灰色bmp位图

源码来自网上,原来只支持24位位图转灰度位图,我增加了32位位图转灰度位图。

//Code By xets007 //转载请注明出处
//Modify By Gergul
#include <windows.h>  

BOOL BMPto8(char *szSourceFile,char *szTargetFile);   

int main(int argc,char* argv[]) 
{  //调用这个函数直接把24位真彩色灰度化  
	BOOL stat=BMPto8("c://1.bmp","c://target.bmp"); 
	return 0; 
}  

BOOL BMPto8(char *szSourceFile,char *szTargetFile) 
{ 
	HANDLE hSourceFile=INVALID_HANDLE_VALUE,hTargetFile=INVALID_HANDLE_VALUE; 
	DWORD dwSourceSize=0,dwTargetSize=0; 
	PBYTE pSource=NULL,pTarget=NULL;  

	//打开源文件
	hSourceFile=CreateFile(szSourceFile,GENERIC_READ,FILE_SHARE_READ,NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL); 
	if(hSourceFile==INVALID_HANDLE_VALUE)   
		return FALSE;  
	//获得文件大小,并分配内存空间 
	dwSourceSize=GetFileSize(hSourceFile,NULL);  
	pSource=(PBYTE)VirtualAlloc(NULL,dwSourceSize,MEM_COMMIT,PAGE_READWRITE); //分配空间失败或者文件太小(BMP文件不可能小于54个字节)    
	if(pSource==NULL||dwSourceSize<=54) 
	{     
		CloseHandle(hSourceFile);   
		return FALSE; 
	}

	//读出bmp文件的全部内容
	DWORD dwReaded = 0; 
	ReadFile(hSourceFile,pSource,dwSourceSize,&dwReaded,NULL);
	CloseHandle(hSourceFile);

	//把读出的内容转换到bmp格式(指针直接指向即可)
	BITMAPFILEHEADER *pSourceFileHeader=(BITMAPFILEHEADER*)pSource;//文件头
	//判断图片是不是BMP文件或者不是24位真彩色    
	BITMAPINFOHEADER *pSourceInfoHeader=(BITMAPINFOHEADER*)(pSource+sizeof(BITMAPFILEHEADER));  
	if(pSourceFileHeader->bfType!=0x4d42)
	{
		VirtualFree(pSource, NULL, MEM_RELEASE); 
		return FALSE;
	}

	//获得bmp位数
	int nPixelCount = 0;
	int nBitNum = pSourceInfoHeader->biBitCount;
	switch (nBitNum)
	{
	case 24:
		nPixelCount = 3;//R G B三量
		break;
	case 32:
		nPixelCount = 4;//R G B A 四量
		break;
	default:
		VirtualFree(pSource, NULL, MEM_RELEASE); 
		return FALSE;
	}
	
	LONG nWidth = pSourceInfoHeader->biWidth; 
	LONG nHeight = pSourceInfoHeader->biHeight;

	//每一行的字节数必须是4的整数倍,如果不是,则需要补齐。
	LONG nSourceWidth = nWidth * nPixelCount;
	if(nSourceWidth%4)
	{
		nSourceWidth=(nSourceWidth/4+1)*4; 
	}
	LONG nTargetWidth = nWidth;
	if(nTargetWidth%4)
	{
		nTargetWidth=(nTargetWidth/4+1)*4; 
	}

	//图像文件的大小
	dwTargetSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD)*256 + nHeight*nTargetWidth; 
	//目标bmp内存
	pTarget=(PBYTE)VirtualAlloc(NULL,dwTargetSize,MEM_COMMIT,PAGE_READWRITE);
	memset(pTarget,0,dwTargetSize); 
	if(pTarget==NULL) 
	{ 
		VirtualFree(pTarget,NULL,MEM_RELEASE); 
		return FALSE;
	}  

	//设置目标bmp文件头数据
	BITMAPFILEHEADER *pTargetFileHeader=(BITMAPFILEHEADER *)pTarget;
	pTargetFileHeader->bfType=pSourceFileHeader->bfType;
	pTargetFileHeader->bfSize=dwTargetSize;
	pTargetFileHeader->bfReserved1=0;
	pTargetFileHeader->bfReserved2=0; 
	pTargetFileHeader->bfOffBits=sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER)+sizeof(RGBQUAD)*256;
	//设置目标bmp信息头数据
	BITMAPINFOHEADER *pTargetInfoHeader =  (BITMAPINFOHEADER *)(pTarget+sizeof(BITMAPFILEHEADER)); 
	pTargetInfoHeader->biBitCount=8;
	pTargetInfoHeader->biClrImportant=0; 
	pTargetInfoHeader->biClrUsed=256; 
	pTargetInfoHeader->biCompression=BI_RGB; 
	pTargetInfoHeader->biHeight=pSourceInfoHeader->biHeight;
	pTargetInfoHeader->biPlanes=1;
	pTargetInfoHeader->biSize=sizeof(BITMAPINFOHEADER);
	pTargetInfoHeader->biSizeImage=nHeight*nTargetWidth;
	pTargetInfoHeader->biWidth=pSourceInfoHeader->biWidth; 
	pTargetInfoHeader->biXPelsPerMeter=pSourceInfoHeader->biXPelsPerMeter; 
	pTargetInfoHeader->biYPelsPerMeter=pSourceInfoHeader->biYPelsPerMeter; 

	//初始化8位灰度图的调色板信息 
	RGBQUAD *pRgb;
	PBYTE pRGBQuadBegin = pTarget + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
	for(int i=0; i<256; i++)
	{   
		pRgb = (RGBQUAD*)(pRGBQuadBegin + i*sizeof(RGBQUAD));
		pRgb->rgbBlue = i;
		pRgb->rgbGreen = i;
		pRgb->rgbRed = i;
		pRgb->rgbReserved = 0; 
	} 

	//转化真彩色图为灰度图 
	for (int h=0; h<nHeight; h++)
	{ 
		for(int w=0; w<nWidth; w++) 
		{
			//把RGB的三个值转化为一个灰度值,所以一个彩色bmp大约比灰度bmp大三倍
			//gray = red * 0.299 + green * 0.587 + blue * 0.114
			int nIndexRgb = pSourceFileHeader->bfOffBits + h*nSourceWidth + w*nPixelCount;	//每个彩色像素点的位置[blue, green, red]
			int nIndexGray = pTargetFileHeader->bfOffBits + h*nTargetWidth + w;		//每个灰色像素点的位置
			pTarget[nIndexGray] = (BYTE)
				( pSource[nIndexRgb]	* 0.114			//蓝
				+ pSource[nIndexRgb+1]	* 0.587			//绿
				+ pSource[nIndexRgb+2]	* 0.299			//红
				);		
		}
	}

	//保存灰度bmp
	hTargetFile = CreateFile(szTargetFile,GENERIC_WRITE,FILE_SHARE_WRITE,  NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
	DWORD dwWrited = 0;
	BOOL stat = WriteFile(hTargetFile,pTarget,dwTargetSize,&dwWrited,NULL);
	CloseHandle(hTargetFile);  
	VirtualFree(pSource,NULL,MEM_RELEASE);
	VirtualFree(pTarget,NULL,MEM_RELEASE);

	return stat; 
}


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值