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;

}

}