From:http://www.physdev.com/phpbb/cms_view_article.php?aid=30
关于CxImage的文章,网上有许多,这里只介绍如何把CxImage与OpenGL结合起来,用于读入多种格式的纹理以及用来把屏幕保存为各种格式的图像文件。
支持的格式有:BMP,GIF,ICO,JP2,FPC,FPG,PCX,PNG,PNM,RAS,TGA,TIF等等。
支持读入透明纹理。
CxImage官方网站:http://www.xdp.it/
//使用CxImage来为OpenGL读入多种格式的纹理
//CxImage是一个开源的图片处理函数库,支持的文件格式有:
//CXIMAGE_FORMAT_BMP
//CXIMAGE_FORMAT_GIF
//CXIMAGE_FORMAT_ICO
//CXIMAGE_FORMAT_JP2
//CXIMAGE_FORMAT_JPC
//CXIMAGE_FORMAT_JPG
//CXIMAGE_FORMAT_PCX
//CXIMAGE_FORMAT_PGX
//CXIMAGE_FORMAT_PNG
//CXIMAGE_FORMAT_PNM
//CXIMAGE_FORMAT_RAS
//CXIMAGE_FORMAT_TGA
//CXIMAGE_FORMAT_TIF
//CXIMAGE_FORMAT_UNKNOWN
//CXIMAGE_FORMAT_WBMP
//CXIMAGE_FORMAT_WMF
//们知道OpenGL自带有读取图形文件作纹理的函数,但功能很弱,只支持BMP图片
//如果要读取其它格式的纹理,就需要用到第三方函数库了。这里我们介绍CxImage
//CxImage下载:www.xdp.it
//以下代码是用来读取JPG文件的,紧供参考。
//读入纹理,支持读入一个alpha纹理,alpha纹理的大小必须与原图一至。
//LoadTexture("pic.jpg",NULL,resultID); //读入单个JPG图片作纹理
//LoadTexture("pic.jpg","pic_alpha.jpg",resultID); //读入一个纹理图,及一个用于透明过滤的alpha图
//LoadTexture("pic.png",NULL,resultID) //读入一个自身带有透明信息的图片作纹理。
bool CCxImage_GLView::LoadTexture(const char *tex_name, const char *alpha_name, unsigned int &texID)
{
// TODO: Add your command handler code here
CxImage image ,alpha,blendTex;//
unsigned char *pImage_RGBA = NULL;
// Load the bitmap using the aux function stored in glaux.lib
//pImage = auxDIBImageLoad(tex_name);
image.Load(tex_name);
// Make sure valid image data was given to pImage, otherwise return false
if(!image.IsValid())
return false;
int sizeX,sizeY;
sizeX = image.GetWidth();
sizeY = image.GetHeight();
float texAspectRatio = (float)sizeX / (float)sizeY;
if(alpha_name && strlen(alpha_name) > 0 )
{
int imageSize_RGB = sizeX * sizeY * 3;
int imageSize_RGBA = sizeX * sizeY * 4;
alpha.Load(alpha_name);
if(!alpha.IsValid())
{
return false;
}
// allocate buffer for a RGBA image
pImage_RGBA = new unsigned char[imageSize_RGBA];
RGBQUAD col_image,col_alpha;
for(int y=0;y<sizeY;y++)
for(int x=0;x<sizeX;x++)
{
col_image = image.GetPixelColor(x,y,false);
col_alpha = alpha.GetPixelColor(x,y,false);
pImage_RGBA[(x+y*sizeX)*4 +0] = col_image.rgbRed;
pImage_RGBA[(x+y*sizeX)*4 +1] = col_image.rgbGreen;
pImage_RGBA[(x+y*sizeX)*4 +2] = col_image.rgbBlue;
pImage_RGBA[(x+y*sizeX)*4 +3] = col_alpha.rgbRed;
}
glGenTextures(1, &texID);
glBindTexture(GL_TEXTURE_2D, texID);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// Don't forget to use GL_RGBA for our new image data we support Alpha transparency now!
// Build Mipmaps (builds different versions of the picture for distances - looks better)
gluBuild2DMipmaps(GL_TEXTURE_2D, 4, sizeX,
sizeY, GL_RGBA, GL_UNSIGNED_BYTE, pImage_RGBA);
if(pImage_RGBA)
{
delete [] pImage_RGBA;
}
}
else if(image.AlphaIsValid())
{
int imageSize_RGB = sizeX * sizeY * 3;
long imageSize_RGBA = sizeX * sizeY * 4;
// allocate buffer for a RGBA image
// pImage_RGBA = new unsigned char[imageSize_RGBA];
image.Encode2RGBA(pImage_RGBA,imageSize_RGBA);
// Generate a texture with the associative texture ID stored in the array
glGenTextures(1, &texID);
// This sets the alignment requirements for the start of each pixel row in memory.
// glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
// Bind the texture to the texture arrays index and init the texture
glBindTexture(GL_TEXTURE_2D, texID);
//Assign the mip map levels and texture info
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// Build Mipmaps (builds different versions of the picture for distances - looks better)
gluBuild2DMipmaps(GL_TEXTURE_2D, 4, sizeX,
sizeY, GL_RGBA, GL_UNSIGNED_BYTE, pImage_RGBA);
image.FreeMemory( pImage_RGBA);
}
else
{
// Generate a texture with the associative texture ID stored in the array
glGenTextures(1, &texID);
// This sets the alignment requirements for the start of each pixel row in memory.
// glPixelStorei (GL_UNPACK_ALIGNMENT, 1);
// Bind the texture to the texture arrays index and init the texture
glBindTexture(GL_TEXTURE_2D, texID);
//Assign the mip map levels and texture info
// glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
// Build Mipmaps (builds different versions of the picture for distances - looks better)
gluBuild2DMipmaps(GL_TEXTURE_2D, 3, sizeX,
sizeY, GL_BGR_EXT, GL_UNSIGNED_BYTE, image.GetBits());
}
//glEnable(GL_TEXTURE_2D);
// Now we need to free the image data that we loaded since openGL stored it as a texture
return true;
}
//用来保存屏幕到图像文件。
void CCxImage_GLView::OnSaveScene()
{
// TODO: Add your command handler code here
static char BASED_CODE szFilter[] = "jpg Files (*.jpg)|*.jpg|bmp Files (*.bmp)|*.bmp|tga Files (*.tga)|*.tga|All Files (*.*)|*.*||";
CString filename;
CString ext = "";
if(filename.IsEmpty())
filename = "NoName";
CFileDialog dlg(false, "jpg",filename, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter);
if(dlg.DoModal() == IDOK)
{
ext = dlg.GetFileExt();
filename = dlg.GetPathName();
//CDC* m_pDC; // Windows设备描述表
//HGLRC m_hRC; // OpenGL渲染描述表
// TODO: Add your command handler code here
wglMakeCurrent(m_pDC->m_hDC,m_hRC);
//这里要注意,如果就面渲染完毕的时候,调用了wglMakeCurrent(NULL,NULL);上面一行就一定要加上。
int expand = 0;
if((m_width *3)%4)
expand = 4 - (m_width*3)%4; //保证位图宽度能被4整除
int mapSize = (m_width*3 +expand) * (m_height);
if(mapSize == 0)
return;
//hDIB = (HGLOBAL) ::GlobalAlloc(GHND,mapSize);
unsigned char * pTmp = new BYTE[mapSize];
if(!pTmp)
return ;
// 读取屏幕像素
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glReadPixels(0, 0, m_width, m_height, GL_BGR_EXT, GL_UNSIGNED_BYTE, pTmp);
// glPixelStorei(GL_PACK_ALIGNMENT, 1);
// BMP信息头
CxImage image;
//image.CreateFromHBITMAP(hbit);
image.CreateFromArray(pTmp,m_width,m_height,24,m_width*3 + expand,false);
image.SetJpegQuality(98); //指定JPG文件的质量(0-100)
if(ext == "jpb")
image.Save(filename,CXIMAGE_FORMAT_JPG);
else if(ext == "bmp")
image.Save(filename,CXIMAGE_FORMAT_BMP);
else if(ext == "tga")
image.Save(filename,CXIMAGE_FORMAT_TGA);
//pFile->Write(pTmp,mapSize*3);
delete[] pTmp;
}
}