在OpenGLES中要求图片的宽和高为2的n次方,因为有了这个要求,使得我们加载纹理的时候就麻烦了许多。经过对加载纹理这个过程的学习和研究,终于把这个问题给解决了。虽然不一定是最好的方法,但是在没有找到更好的方法前,将就着用吧。
思路很简单:就是将jpg、png文件解码到一个DC中,然后将DC中的保持到一个位图结构中,在保存之前对DC进行加工,使它的宽高大小变成2的n次方,最后从位图结构中读出数据作为纹理数据。解码我用的是wince下自带的IImage组件来解码,如果你有更好,速度更快的方法那就更好咯。废话少说,下面贴代码:
//计算绘制目标矩形区域
void CPicScan3DDlg::CalcuteDrawArea(CRect DestRect, CRect *pDrawRect, int nWidth, int nHeight)
{
if (DestRect.Width() > nWidth && DestRect.Height() > nHeight)
{
pDrawRect->left = DestRect.left + (DestRect.Width() - nWidth)/2;
pDrawRect->top = DestRect.top + (DestRect.Height() - nHeight)/2;
pDrawRect->right = pDrawRect->left + nWidth;
pDrawRect->bottom = pDrawRect->top + nHeight;
}
else
{
if (DestRect.Height() * nWidth > DestRect.Width() * nHeight)
{
int w = DestRect.Width();
int h = (int)( (float)w / (float)nWidth * nHeight );
pDrawRect->left = DestRect.left;
pDrawRect->top = ( DestRect.Height() - h ) / 2 + DestRect.top;
pDrawRect->right = pDrawRect->left + w;
pDrawRect->bottom = pDrawRect->top + h;
}
else if (DestRect.Height() * nWidth < DestRect.Width() * nHeight)
{
int h = DestRect.Height();
int w = (int)( (float)h / (float)nHeight * nWidth );
pDrawRect->left = ( DestRect.Width() - w ) / 2 + DestRect.left;
pDrawRect->top = DestRect.top;
pDrawRect->right = pDrawRect->left + w;
pDrawRect->bottom = pDrawRect->top + h;
}
else
{
pDrawRect->left = DestRect.left;
pDrawRect->top = DestRect.top;
pDrawRect->right = DestRect.right;
pDrawRect->bottom = DestRect.bottom;
}
}
}
//把给定设备环境内容保存成位图
void CPicScan3DDlg::SaveDCToBMP(HDC hDC, CRect sRect, int nWidth,int nHeight,CBitmap *pBitMap)
{
//定义图形色深
int iPixel = 24;
//位图信息头
LPBITMAPINFO lpbmih = new BITMAPINFO;
lpbmih->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
lpbmih->bmiHeader.biWidth = nWidth;
lpbmih->bmiHeader.biHeight = nHeight;
lpbmih->bmiHeader.biPlanes = 1;
lpbmih->bmiHeader.biBitCount = iPixel;
lpbmih->bmiHeader.biCompression = BI_RGB;
lpbmih->bmiHeader.biSizeImage = 0;
lpbmih->bmiHeader.biXPelsPerMeter = 0;
lpbmih->bmiHeader.biYPelsPerMeter = 0;
lpbmih->bmiHeader.biClrUsed = 0;
lpbmih->bmiHeader.biClrImportant = 0;
//创建位图数据
HDC hdcMem;
HBITMAP hBitMap = NULL;
CDC *pMemDC = NULL;
BYTE *pBits;
hdcMem = CreateCompatibleDC(hDC);
hBitMap = CreateDIBSection(hdcMem,lpbmih,DIB_RGB_COLORS,(void **)&pBits,NULL,0);
pBitMap->Attach(hBitMap);
pMemDC = new CDC;
pMemDC->Attach(hdcMem);
pMemDC->SelectObject(pBitMap);
pMemDC->StretchBlt(0,0,nWidth,nHeight,CDC::FromHandle(hDC),sRect.left,sRect.top, sRect.Width(), sRect.Height(),SRCCOPY);
DeleteObject(hBitMap);
pMemDC->DeleteDC();
delete pMemDC; pMemDC = NULL;
delete lpbmih; lpbmih = NULL;
}
//读取缩略图为纹理
BOOL CPicScan3DDlg::LoadThumhbnailImage(TCHAR* szFileName, GLuint *id)
{
IImagingFactory *pImgFactory = NULL;
IImage *pImage = NULL;
IImage *pImgThumbnail = NULL;
ImageInfo Info;
CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (SUCCEEDED(CoCreateInstance(CLSID_ImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IImagingFactory, (void **) &pImgFactory)))
{
if (SUCCEEDED(pImgFactory->CreateImageFromFile(szFileName, &pImage)))
{
pImage->GetImageInfo(&Info);
CRect rt;
CRect rect(0,0,179,128);
CBrush brush(RGB(0,0,0));
m_ThumhDC.FillRect(rect, &brush);
brush.DeleteObject();
CalcuteDrawArea(rect, &rt, Info.Width, Info.Height);
pImage->GetThumbnail(rt.Width(), rt.Height(), &pImgThumbnail);
pImgThumbnail->Draw(m_ThumhDC.m_hDC, &rt, NULL);
if (!pImage)
{
pImage->Release();
pImage = NULL;
}
if (!pImgThumbnail)
{
pImgThumbnail->Release();
pImage = NULL;
}
CBitmap tempBmp;
SaveDCToBMP(m_ThumhDC.m_hDC, rect, 128, 128, &tempBmp);
BITMAP bm;
tempBmp.GetBitmap(&bm);
unsigned char *bitmap = (unsigned char *)bm.bmBits;
unsigned char tmpRGB;
for (LONG i = 0; i<bm.bmHeight*bm.bmWidth*3; i+=3)
{
tmpRGB = bitmap[i];
bitmap[i] = bitmap[i+2];
bitmap[i+2] = tmpRGB;
}
glGenTextures(1, id);
glBindTexture(GL_TEXTURE_2D, *id);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 128, 128, 0, GL_RGB, GL_UNSIGNED_BYTE, bitmap);
tempBmp.DeleteObject();
}
else
{
pImgFactory = NULL;
pImage = NULL;
CoUninitialize();
return FALSE;
}
pImgFactory->Release();
pImgFactory = NULL;
}
else
{
pImgFactory = NULL;
pImage = NULL;
CoUninitialize();
return FALSE;
}
CoUninitialize();
return TRUE;
}
//读取图片文件为纹理(非缩略图)
BOOL CPicScan3DDlg::LoadIntegrityImage(TCHAR* szFileName, GLuint *id)
{
IImagingFactory *pImgFactory = NULL;
IImage *pImage = NULL;
ImageInfo Info;
CoInitializeEx(NULL, COINIT_MULTITHREADED);
if (SUCCEEDED(CoCreateInstance(CLSID_ImagingFactory, NULL, CLSCTX_INPROC_SERVER, IID_IImagingFactory, (void **) &pImgFactory)))
{
if (SUCCEEDED(pImgFactory->CreateImageFromFile(szFileName, &pImage)))
{
pImage->GetImageInfo(&Info);
CRect rt;
CRect rect(0,0,640,512);
CBrush brush(RGB(0,0,0));
m_IntegDC.FillRect(rect, &brush);
brush.DeleteObject();
CalcuteDrawArea(rect, &rt, Info.Width, Info.Height);
pImage->Draw(m_IntegDC.m_hDC, &rt, NULL);
if (!pImage)
{
pImage->Release();
pImage = NULL;
}
CBitmap tempBmp;
SaveDCToBMP(m_IntegDC.m_hDC, rect, 512, 512, &tempBmp);
BITMAP bm;
tempBmp.GetBitmap(&bm);
unsigned char *bitmap = (unsigned char *)bm.bmBits;
unsigned char tmpRGB;
for (LONG i = 0; i<bm.bmHeight*bm.bmWidth*3; i+=3)
{
tmpRGB = bitmap[i];
bitmap[i] = bitmap[i+2];
bitmap[i+2] = tmpRGB;
}
glGenTextures(1, id);
glBindTexture(GL_TEXTURE_2D, *id);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterx(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 512, 512, 0, GL_RGB, GL_UNSIGNED_BYTE, bitmap);
tempBmp.DeleteObject();
}
else
{
pImgFactory = NULL;
pImage = NULL;
CoUninitialize();
return FALSE;
}
pImgFactory->Release();
pImgFactory = NULL;
}
else
{
pImgFactory = NULL;
pImage = NULL;
CoUninitialize();
return FALSE;
}
CoUninitialize();
return TRUE;
}
哈哈,这样就可以完成只要IImage能解码的文件格式,都能做为OpenGLES的纹理了。