代码都是在程序中截取的部分的较为关键性的内容
//创建兼容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);
透明设置