16位BMP图转32位BMP图

最近在做OCR识别,在本机上做好的程序在服务器上的VM虚拟机上出现了问题,进行调试,发现原来服务器的VM虚拟机里面的颜色是16位色彩的,截的图也默认是16位,而tesseract是不识别16位的,因此我就想把16位改成32位。本来我以为16位就是两种颜色共用1个字节,以为也是rgba的格式,结果在改写的过程发现转换的结果一直不对,经过4!变换对应,我意识到我的思路出现问题,通过查找,发现16位是565或者0555的模式(这个要注意高字节低字节的问题),于是在尝试了一番,果然可用,下面贴上我的转换代码,代码比较粗糙,但是希望给困惑中的人带来帮助。注意:这个代码适用于VM虚拟机中的xp16位颜色模式,其他的16位需要具体分析。

 //后面用到的数据,我在构造函数有初始化
 BITMAPFILEHEADER *pBmpFileHeader;
 BITMAPINFOHEADER *pBmpInfoHeader;
 BYTE *pBmpData;

bool OCR::Convert16Bit232Bit(char *source, char *savefile)
{
	//读文件
        //前面这里的有些函数是我自己用来校验文件存在和后缀的,去掉不影响使用,直接从读文件开始就可以了 
        int len = helper->GetStringLength(source);
	char *fullpath = new char[len + 10];
	memset(fullpath, 0 ,sizeof(char) * (len + 10));
	helper->GetExtensionFilePath(source, fullpath);
	if (!helper->FileIsExist(fullpath))
	{
#ifdef _CONSOLE_SHOW_
		std::cout << "ERROR 1. The file can\'t open." << std::endl; 
#endif
		delete[] fullpath;
		return false;
	}

	FILE *fp = fopen(fullpath, "rb");
	if (NULL != fullpath)
	{
		delete[] fullpath;
		fullpath = NULL;
	}
	if (!fp)
	{
#ifdef _CONSOLE_SHOW_
		std::cout << "ERROR 2. The file can\'t open." << std::endl; 
#endif
		return false;
	}
	pBmpFileHeader = new BITMAPFILEHEADER();
	pBmpInfoHeader = new BITMAPINFOHEADER();
	fread(pBmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
	fread(pBmpInfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);
	pBmpData = new BYTE[pBmpInfoHeader->biSizeImage];
	if (!pBmpData)
	{
#ifdef _CONSOLE_SHOW_
		std::cout << "ERROR 3. The memory assigned fail." << std::endl;
#endif
		return false;
	}
	memset(pBmpData, 0, sizeof(BYTE) * (pBmpInfoHeader->biSizeImage));
	fread(pBmpData, sizeof(BYTE), pBmpInfoHeader->biSizeImage, fp);
	fclose(fp);
	fp = NULL;
  

	//转换成32位
	int lineBytes = (pBmpInfoHeader->biWidth * 32 + 31) / 32 * 4;
	int oldLineBytes = (pBmpInfoHeader->biWidth * 16 + 31) / 32 *4;
	int oldSize = pBmpInfoHeader->biSizeImage;
	pBmpInfoHeader->biBitCount = 32;
	pBmpInfoHeader->biSizeImage = lineBytes * pBmpInfoHeader->biHeight;

	BYTE *pData = new BYTE[pBmpInfoHeader->biSizeImage];
	memset(pData, 255, sizeof(BYTE) * pBmpInfoHeader->biSizeImage);

	WORD *temp = (WORD*)pBmpData;

	for (int i = 0; i < pBmpInfoHeader->biHeight; ++i)
	{
		for (int j = 0; j < pBmpInfoHeader->biWidth; ++j)
		{
                        //变量声明应该写在循环外,可以提高速度,尤其是图比较大时
			int color1 = (float)(((*(temp + i * oldLineBytes/2 + j)) & 0x1f)) / 31.0f * 255;
			int color2 = (float)(((*(temp + i * oldLineBytes/2 + j)) & 0x3e0) >> 5) / 31.0f * 255;
			int color3 = (float)(((*(temp + i * oldLineBytes/2 + j)) & 0x7c00) >> 10) / 31.0f * 255;

			//红色
			*(pData + i * lineBytes + 4 * j + 2) = color3;
			//绿色  //e0 7
			*(pData + i * lineBytes + 4 * j + 1) = color2;
			//蓝色
			*(pData + i * lineBytes + 4 * j + 0) = color1;
			//aphla
			*(pData + i * lineBytes + 4 * j + 3) = 255;
			
		}
	}

	//写
	if (savefile != NULL)
	{
		fp = fopen(savefile, "wb");
		if (!fp)
		{
#ifdef _CONSOLE_SHOW_
			std::cout << "ERROR 6. The file can\'t write." << std::endl; 
#endif
                        //这里应该释放new出的内存,在网页上编写比较费劲,就不改了
                        return false;
		}

		fwrite(pBmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
		fwrite(pBmpInfoHeader, sizeof(BITMAPINFOHEADER), 1, fp);
		fwrite(pData, sizeof(BYTE), pBmpInfoHeader->biSizeImage, fp);
		fclose(fp);
		fp = NULL;
	}

	if (NULL != pBmpData)
	{
		delete[] pBmpData;
		pBmpData = NULL;
	}
	if (NULL != pBmpFileHeader)
	{
		delete pBmpFileHeader;
		pBmpFileHeader = NULL;
	}
	if (NULL != pBmpInfoHeader)
	{
		delete pBmpInfoHeader;
		pBmpInfoHeader = NULL;
	}
	if (NULL != pData)
	{
		delete[] pData;
		pData = NULL;
	}
	return true;
}

 



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值