输出BMP小结

代码都是在程序中截取的部分的较为关键性的内容

	//创建兼容DC
	CDC *pDC = drawContext->pDC;
	int width = drawContext->viewRect.right / 2;
	int height = drawContext->viewRect.top / 2;
	CDC compatibleDC;
	compatibleDC.CreateCompatibleDC(pDC);
	//为兼容DC建立兼容位图
	CBitmap bitmapData;
	bitmapData.CreateCompatibleBitmap(pDC, width, height);
	compatibleDC.SelectObject(&bitmapData);
创建兼容DC(下边说的DC都是兼容DC),在上边绘制图形

	BMP信息头定义
	BITMAPINFOHEADER bitmapInfoHeader;
	bitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
	bitmapInfoHeader.biWidth = width;
	bitmapInfoHeader.biHeight = height;
	bitmapInfoHeader.biPlanes = 1;
	bitmapInfoHeader.biBitCount = readPixelByte * 8;   //先设置为32
	bitmapInfoHeader.biCompression = 0;
	bitmapInfoHeader.biSizeImage = width * height * readPixelByte;
	bitmapInfoHeader.biXPelsPerMeter = 0;
	bitmapInfoHeader.biYPelsPerMeter = 0;
	bitmapInfoHeader.biClrUsed = 0;
	bitmapInfoHeader.biClrImportant = 0;
定义一个信息头,因为在下边从DC的位图中获取像素值时要用到

	//申请内存保存位图数据
	byte *pData = new byte[width * height * writePixelByte];    //写进BMP的数据
	byte *pByte = new byte[width * height * readPixelByte];     //从兼容DC获取的位图为32位
	//memset(pByte, 255, sizeof(byte) * width * height * (pixelSize + 1));
	if (!GetDIBits(compatibleDC.m_hDC, (HBITMAP)bitmapData.m_hObject, 0, height, pByte, (LPBITMAPINFO)&bitmapInfoHeader, DIB_RGB_COLORS))     //获取位图数据
	{
		AfxMessageBox(_T("读取位图数据失败"));
	}
	//去掉pByte中alpha值,放在pData,保存为24位图片
	if (mbitmap.bmBitsPixel == 32)
	{
		byte *tempData = pData;
		byte *tempByte = pByte;
		for (int i = 0; i < height; i++)
		{
			for (int j = 0; j < width; j++)
			{
				*(tempData + 0) = *(tempByte + 0);
				*(tempData + 1) = *(tempByte + 1);
				*(tempData + 2) = *(tempByte + 2);
				tempData += 3;
				tempByte += 4;
			}
		}
	}
	//图片颠倒
	byte a[3] = { 0, 0, 0 };
	for (int i = 0; i < height / 2; i++)
	{
		for (int j = 0; j < width; j++)
		{
		a[0] = *(pData + (i * width + j) * writePixelByte + 0);
		a[1] = *(pData + (i * width + j) * writePixelByte + 1);
		a[2] = *(pData + (i * width + j) * writePixelByte + 2);
		int b = height - 1 - i;
		*(pData + (i * width + j) * writePixelByte + 0) = *(pData + (b * width + j) * writePixelByte + 0);
		*(pData + (i * width + j) * writePixelByte + 1) = *(pData + (b * width + j) * writePixelByte + 1);
		*(pData + (i * width + j) * writePixelByte + 2) = *(pData + (b * width + j) * writePixelByte + 2);
		*(pData + (b * width + j) * writePixelByte + 0) = a[0];
		*(pData + (b * width + j) * writePixelByte + 1) = a[1];
		*(pData + (b * width + j) * writePixelByte + 2) = a[2];
		}
	}
上边用GetBits函数从DC的位图中读取了像素值,读取出来的是32位GL_BGRA数据,可以把它转换为24位GL_BGR数据,另外在输出的时候,可能会有图片颠倒问题

	//宽高字节的对齐,对宽高调整
	int justWidth = width;
	int justHeight = height;
	if ((width + 3) / 4 * 4 != width)      //需要对宽4字节对齐设置
	{
		justWidth = (width + 3) / 4 * 4;
	}
	if ((height + 1) / 2 * 2 != height)   //需要对高2字节对齐设置
	{
		justHeight = (height + 1) / 2 * 2;
	}
读取BMP作为纹理,个人认为最好读取24位BMP(32位可能由于OpenGL版本问题?报错),转为24位BMP,注意:宽必须为4整数倍,高必须为2整数倍。所以涉及到了字节对齐问题

	BITMAPFILEHEADER bf;
	bf.bfType = 0x4D42;	//"BM"
	bf.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + justWidth * justHeight * writePixelByte;
	bf.bfReserved1 = 0;
	bf.bfReserved2 = 0;
	bf.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);
	BMP信息头定义
	BITMAPINFOHEADER bi;
	bi.biSize = sizeof(BITMAPINFOHEADER);
	bi.biWidth = justWidth;
	bi.biHeight = justHeight;
	bi.biPlanes = 1;
	bi.biBitCount = writePixelByte * 8;   //24
	bi.biCompression = 0;
	bi.biSizeImage = justWidth * justHeight * writePixelByte;
	bi.biXPelsPerMeter = 0;
	bi.biYPelsPerMeter = 0;
	bi.biClrUsed = 0;
	bi.biClrImportant = 0;

	//CString  filename;
	tempPropertyType = this->model->m_pPropertyTypes->at(displayControl->m_dispPropertyIndex);
	filename.Format(".....");
	pFile = fopen(filename, "wb");
	if (!pFile)
	{
		AfxMessageBox(_T("保存BMP失败"));
	}
	fwrite(&bf, sizeof(bf), 1, pFile);
	fwrite(&bi, sizeof(bi), 1, pFile);
	//----------------宽高字节的对齐(将width与justWidth,height与justHeight分别分开处理)------------
	if ((width + 3) / 4 * 4 != width)  //需要对宽4字节对齐设置
	{
		//-----对0-height输出
		int sizeW = (justWidth - width) * writePixelByte;
		byte *tempbyteW = new byte[sizeW];
		memset(tempbyteW, 255, sizeW);
		for (int i = 0; i < height; i++)   //0-height,宽4字节补齐
		{
			fwrite((pData + i * width * writePixelByte), 1, width * writePixelByte, pFile);
			fwrite(tempbyteW, 1, sizeW, pFile);
		}
		delete[] tempbyteW;
		//-----对height-justHeight输出
		if ((height + 1) / 2 * 2 != height)   //height-justHeight,宽4字节补齐,高2字节补齐
		{
			int sizeH = (justHeight - height) * justWidth * writePixelByte;
			byte *tempbyteH = new byte[sizeH];
			memset(tempbyteH, 255, sizeH);
			fwrite(tempbyteH, 1, sizeH, pFile);
			delete[] tempbyteH;
		}
	}
	else   //宽不用对齐,直接输出
	{
		//-----对0-height输出
		fwrite(pData, 1, width * height * writePixelByte, pFile);
		//----对height-justHeight输出
		if ((height + 1) / 2 * 2 != height)  //height-justHeight,宽不补齐,高2字节补齐
		{
			int size = (justHeight - height) * width * writePixelByte;
			byte *tempbyte = new byte[size];
			memset(tempbyte, 255, size);
			fwrite(tempbyte, 1, size, pFile);
			delete[] tempbyte;
		}
	}
	fclose(pFile);

对齐处理

	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, m_width, m_height, 0, GL_BGR, GL_UNSIGNED_BYTE, pData);
贴图源通道用GL_BGR

				GLuint m_textureName;
				glGenTextures(1, &m_textureName);
重复调用会引起内存泄漏

glDepthMask(GL_FALSE);
glBegin(GL_QUADS);
..
..
glEnd();
glDisable(GL_TEXTURE_2D);

透明设置














  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值