分离位图的RGB通道

位图文件结构很好分析,不像png图像。

//处理位图
//@szPath: 位图的路径
VOID HandleBitmap(CHAR* szPath)
{
	//路径不为空 字符串地址不为空
	if (!strlen(szPath) || !szPath)
		return;
	//判断是否是位图文件
	INT nPathLen = strlen(szPath);
	_strupr(szPath);
	if (strncmp(&szPath[nPathLen - 4], ".BMP", 4))
		return;

	HANDLE hFile = 0;			//位图的句柄
	INT nFileSize;				//位图的总大小
	LPBYTE pBuffer = 0;			//整个位图的缓冲区
	DWORD dwByte;				//读取数据的大小
	BITMAPFILEHEADER stFile;	//位图文件头
	BITMAPINFOHEADER stInfo;	//位图信息头
	LPBYTE pData;				//位图RGB数据
	LPBYTE pDataRGB[3] = { 0 };	//只带一个颜色的RGB数据
	BOOL bTip;					//辅助标志
	INT nLineLen;				//位图一行RGB数据的大小
	INT nBit;					//颜色位
	HANDLE hWrite = 0;			//写入的文件句柄
	CHAR szNewPath[MAX_PATH];	//新位图路径
	do
	{
		//打开位图
		hFile = CreateFileA(szPath, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
		if (!hFile)
			break;
		//获取位图大小
		nFileSize = GetFileSize(hFile, 0);
		if(!nFileSize)
			break;
		//申请空间
		pBuffer = (LPBYTE)VirtualAlloc(0, nFileSize, MEM_COMMIT, PAGE_READWRITE);
		if(!pBuffer)
			break;
		//读取位图数据
		ReadFile(hFile, pBuffer, nFileSize, &dwByte, 0);
		if(!dwByte)
			break;
		//关闭位图句柄
		CloseHandle(hFile);
		hFile = 0;
		//复制位图文件头 位图信息头 和位图RGB数据
		CopyMemory(&stFile, pBuffer, sizeof(BITMAPFILEHEADER));
		CopyMemory(&stInfo, (pBuffer + sizeof(BITMAPFILEHEADER)), sizeof(BITMAPINFOHEADER));
		pData = (pBuffer + sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER));
		if (stInfo.biBitCount != 24)
			break;

		//申请内存
		bTip = FALSE;
		for (int nIndex = 0; nIndex < 3; nIndex++)
		{
			pDataRGB[nIndex] = (LPBYTE)VirtualAlloc(0, nFileSize - sizeof(BITMAPFILEHEADER) - sizeof(BITMAPINFOHEADER), MEM_COMMIT, PAGE_READWRITE);
			if (!pDataRGB[nIndex])
			{
				bTip = TRUE;
				break;
			}
		}
		//判断申请是否失败
		if(bTip)
			break;
		//获取位图一行颜色的长度和颜色位
		nLineLen = (stInfo.biWidth*stInfo.biBitCount / 8 + 3) / 4 * 4;
		nBit = stInfo.biBitCount / 8;
		//提取指定RGB颜色到指定内存
		for (int nHeight = 0; nHeight < stInfo.biHeight; nHeight++)
		{
			for (int nWidth = 0; nWidth < stInfo.biWidth; nWidth++)
			{
				for (int nRGB = 0; nRGB < nBit; nRGB++)
				{
					pDataRGB[nRGB][nLineLen*nHeight + nWidth * nBit + nRGB] = pData[nLineLen*nHeight + nWidth * nBit + nRGB];
				}
			}
		}
		//分别写入到位图文件
		for (int nIndex = 0; nIndex < 3; nIndex++)
		{
			//拼装新的位图文件头
			wsprintf(szNewPath,"%s_%d_%s",szPath,nIndex,".BMP");
			//创建新的单色位图文件
			hWrite = CreateFileA(szNewPath, GENERIC_WRITE, FILE_SHARE_WRITE, 0, OPEN_ALWAYS, 0, 0);
			if (!hWrite)
				break;
			//写入位图文件头
			WriteFile(hWrite, &stFile, sizeof(BITMAPFILEHEADER), &dwByte, 0);
			if(!dwByte)
				break;
			//写入位图信息头
			WriteFile(hWrite, &stInfo, sizeof(BITMAPINFOHEADER), &dwByte, 0);
			if(!dwByte)
				break;
			//写入单色位图数据
			WriteFile(hWrite, pDataRGB[nIndex], nFileSize - sizeof(BITMAPFILEHEADER) - sizeof(BITMAPINFOHEADER), &dwByte, 0);
			if(!dwByte)
				break;
			//关闭文件句柄
			CloseHandle(hWrite);
			hWrite = 0;
		}

	} while (0);
	//释放。。。

	if (hFile)
		CloseHandle(hFile);
	if (pBuffer)
		VirtualFree(pBuffer, 0, MEM_RELEASE);
	for (int nIndex = 0; nIndex < 3; nIndex++)
		if (pDataRGB[nIndex])
			VirtualFree(pDataRGB[nIndex], 0, MEM_RELEASE);
	if (hWrite)
		CloseHandle(hWrite);
}

Github

猜你喜欢

转载自blog.csdn.net/zzy1448331580/article/details/93352358
今日推荐