OpenGL本身并没有带图象文件的读取函数,D3DX则有,以前我用的IPicture的接口来加载图象,但是TGA ,MNG PNG 等图象它并不支持.需要其他的代码来加载TGA等,非常不方便,最倒霉的是,代码的问题很多,经常不能成功加载一些图象.早就想把那个该死的库移植到DevIL上了,但是人懒,一直等到今天,呵呵。终于做了个简单的包装了。 代码很乱,只加了读取图象到建立OpenGL纹理,应该还有更广泛的用途的.比如SaveImage等. 回头等有空的时候做一个更好用的。 这里的的代码只有一个文件,是一个dll,自己编译一下就可以了。DevIL当前为1.6.7请到http://www.sourceforge.net/Projects/openil/去下载,说明一下,DevIL原来叫OpenIL,是一个学习了OpenGL的库,因为某些原因,改名为devil了。
/*** Source code for gltexture.h ***/ #ifndef _GL_TEXTURE_H_ #define _GL_TEXTURE_H_
#include <windows.h> #include <GL\gl.h>
typedef struct ImageSize { int width,height; int bits; }IMAGESIZE,*PIMAGESIZE;
typedef unsigned char* IMAGEDATA;
typedef struct { int width,height; unsigned char* pdata; int bits; GLuint format; int ImageID; }DIBTEXDATA,*PDIBTEXDATA;
#ifdef _DEBUG #pragma comment(lib,"gltextured.lib") #else #pragma comment(lib,"gltexture.lib") #endif
typedef GLuint GLTEXTURE;
extern "C" int FlowToPower2(int w); extern "C" IMAGEDATA LoadBlankImage(IMAGESIZE size); extern "C" int SetImagePixel(unsigned char* image,int x,int y,IMAGESIZE size,unsigned char cl[4]); extern "C" int GetImagePixel(unsigned char* image,int x,int y,IMAGESIZE size,unsigned char cl[4]); extern "C" void SetKeyColorAlpha(unsigned char* image,IMAGESIZE size,unsigned char cl[4],int r); extern "C" int IsPowerOfTwo(int n); extern "C" int RoundFourByte(int n); extern "C" DIBTEXDATA LoadTexData(char* filename); extern "C" DIBTEXDATA CreateDibTexData(int w,int h); extern "C" void FreeDibTexData(DIBTEXDATA dib); extern "C" void SetTexAlpha(GLubyte color[],GLubyte alpha,DIBTEXDATA dib,int r); extern "C" void SetTexPixel(int x,int y,GLubyte color[],DIBTEXDATA dib); extern "C" void GetTexPixel(int x,int y,GLubyte color[],DIBTEXDATA dib); extern "C" GLuint BuildTexture(char* filename); extern "C" GLuint BuildTransparencyTexture(char* filename,GLubyte color[],GLubyte alpha,int r); extern "C" GLuint BuildTextureFromImage(unsigned char* image,IMAGESIZE size); extern "C" GLuint BuildTextureFromRGBImage(unsigned char* image,IMAGESIZE size);
#endif
/** 以下为.def文件, **/
EXPORTS LoadBlankImage SetImagePixel GetImagePixel SetKeyColorAlpha IsPowerOfTwo RoundFourByte LoadTexData CreateDibTexData FreeDibTexData SetTexAlpha SetTexPixel GetTexPixel BuildTexture BuildTransparencyTexture BuildTextureFromImage BuildTextureFromRGBImage
+++++++++++++++++++++++++++++++++++++++++++++++++++++ 下面为真正代码 +++++++++++++++++++++++++++++++++++++++++++++++++++++ /** source code for gltexture.cpp **/ // GLTexture.cpp : Defines the entry point for the DLL application. //
#include "stdafx.h" #include <fstream> #include <windows.h> #include <GL\gl.h> #include <GL\glu.h> #include <math.h> using namespace std;
#include <IL/il.h> #include <IL/ilu.h>
#pragma comment(lib,"Devil.lib") #pragma comment(lib,"ILu.lib")
/**** 以下内容为需要写到头文件里 ****/ typedef struct ImageSize { int width,height; int bits; }IMAGESIZE,*PIMAGESIZE;
typedef unsigned char* IMAGEDATA;
typedef struct { int width,height; unsigned char* pdata; int bits; GLuint format; int ImageID; }DIBTEXDATA,*PDIBTEXDATA;
extern "C" IMAGEDATA LoadBlankImage(IMAGESIZE size); extern "C" int SetImagePixel(unsigned char* image,int x,int y,IMAGESIZE size,unsigned char cl[4]); extern "C" int GetImagePixel(unsigned char* image,int x,int y,IMAGESIZE size,unsigned char cl[4]); extern "C" void SetKeyColorAlpha(unsigned char* image,IMAGESIZE size,unsigned char cl[4],int r); extern "C" int IsPowerOfTwo(int n);
extern "C" int RoundFourByte(int n); extern "C" DIBTEXDATA LoadTexData(char* filename); extern "C" DIBTEXDATA CreateDibTexData(int w,int h); extern "C" void FreeDibTexData(DIBTEXDATA dib); extern "C" void SetTexAlpha(GLubyte color[],GLubyte alpha,DIBTEXDATA dib,int r); extern "C" void SetTexPixel(int x,int y,GLubyte color[],DIBTEXDATA dib); extern "C" void GetTexPixel(int x,int y,GLubyte color[],DIBTEXDATA dib); extern "C" GLuint BuildTexture(char* filename); extern "C" GLuint BuildTransparencyTexture(char* filename,GLubyte color[],GLubyte alpha,int r); extern "C" GLuint BuildTextureFromImage(unsigned char* image,IMAGESIZE size); extern "C" GLuint BuildTextureFromRGBImage(unsigned char* image,IMAGESIZE size);
/**** 以上内容为需要写到头文件里 ****/ #pragma comment(lib,"opengl32.lib") #pragma comment(lib,"glu32.lib") void FreeImageData(unsigned char* pData); BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { static bool ilIsInit = false; if(ul_reason_for_call == DLL_PROCESS_ATTACH) { if(ilIsInit == false) { // Needed to initialize DevIL. ilInit(); ilIsInit = true; }
}
if(ul_reason_for_call == DLL_PROCESS_DETACH) { if(ilIsInit == true) { // Needed to initialize DevIL. ilShutDown(); ilIsInit = false; } } return TRUE; }
extern "C" int FlowToPower2(int w) { return 1 << (int)floor((log((double)w)/log(2.0f)) + 0.5f); }
extern "C" DIBTEXDATA LoadTexData(char* filename) { int Width = 0; int Height = 0; int Bpp = 0; int Format = 0; int Depth = 0;
int NewW = 0; int NewH = 0;
GLubyte* prgba = NULL; ILuint ImageID;
ilGenImages(1,&ImageID); ilBindImage(ImageID); ILboolean IsLoaded = ilLoadImage(filename); if(! IsLoaded) { goto exit_entry; }
Width = ilGetInteger(IL_IMAGE_WIDTH); Height = ilGetInteger(IL_IMAGE_HEIGHT); Bpp = ilGetInteger(IL_IMAGE_BPP); Format = ilGetInteger(IL_IMAGE_FORMAT); Depth = ilGetInteger(IL_IMAGE_DEPTH);
NewW = FlowToPower2(Width); NewH = FlowToPower2(Height);
if(NewW != Width || NewH != Height ) { iluScale(NewW,NewH,Depth); } if(Format != IL_RGBA) { ilConvertImage(IL_RGBA,ilGetInteger(IL_IMAGE_TYPE)); }
prgba = ilGetData(); DIBTEXDATA dib; exit_entry: //纹理数据已经创建好了,现在可以保存大小后返回 dib.height = NewH; dib.width = NewW; dib.pdata = prgba; dib.bits =32; dib.format = GL_RGBA; dib.ImageID = ImageID; return dib; }
extern "C" DIBTEXDATA CreateDibTexData(int w,int h) { DIBTEXDATA pt; int size = w * h* 4 ; pt.height = h; pt.width = w; IMAGESIZE isize; isize.height = h; isize.width = w; isize.bits = 32; pt.pdata = LoadBlankImage(isize); pt.ImageID = -1;
return pt; }
extern "C" void FreeDibTexData(DIBTEXDATA dib) { if( ilIsImage(dib.ImageID) ) { ilDeleteImages(1,(const ILuint*)&dib.ImageID); return ; } if (dib.pdata) { FreeImageData(dib.pdata); return ; } }
extern "C" void SetTexAlpha(GLubyte color[],GLubyte alpha,DIBTEXDATA dib,int r) { int size=dib.height*dib.width*4; for(int i=0;i<size;i+=4) { if(abs(color[0]-dib.pdata[i+2])<=r&& abs(color[1]-dib.pdata[i+1])<=r&& abs(color[2]-dib.pdata[i])<=r ) { dib.pdata[i+3]=alpha; } } }
extern "C" void SetTexPixel(int x,int y,GLubyte color[],DIBTEXDATA dib) { GLubyte* pstart = dib.pdata+(dib.height-1-y)*dib.width*4; pstart += x*4;
pstart[0]=color[2];//r pstart[1]=color[1];//g pstart[2]=color[0];//b pstart[3]=color[3];//a
} extern "C" void GetTexPixel(int x,int y,GLubyte color[],DIBTEXDATA dib) { GLubyte* pstart = dib.pdata+(dib.height-1-y)*dib.width*4; pstart += x*4;
color[0]=pstart[2];//r color[1]=pstart[1];//g color[2]=pstart[0];//b color[3]=pstart[3];//a
} extern "C" GLuint BuildTexture(char* filename) {
GLubyte* prgba; ILuint ImageID; ilGenImages(1,&ImageID); ilBindImage(ImageID); ILboolean IsLoaded = ilLoadImage(filename); if(! IsLoaded) return 0;
int Width = ilGetInteger(IL_IMAGE_WIDTH); int Height = ilGetInteger(IL_IMAGE_HEIGHT); int Bpp = ilGetInteger(IL_IMAGE_BPP); int Format = ilGetInteger(IL_IMAGE_FORMAT); int Depth = ilGetInteger(IL_IMAGE_DEPTH);
int NewW = FlowToPower2(Width); int NewH = FlowToPower2(Height);
if(NewW != Width || NewH != Height ) { iluScale(NewW,NewH,Depth); }
if(Format != IL_RGBA) { ilConvertImage(IL_RGBA,ilGetInteger(IL_IMAGE_TYPE)); }
prgba = ilGetData(); IMAGESIZE size; size.bits = 32; size.width = NewW; size.height =NewH;
if(prgba == 0) { ilDeleteImages(1,&ImageID); return 0; } GLuint t = BuildTextureFromImage(prgba,size); ilDeleteImages(1,&ImageID); return t; }
extern "C" GLuint BuildTransparencyTexture(char* filename,GLubyte color[],GLubyte alpha,int r) {
GLuint texture;
DIBTEXDATA dib=LoadTexData(filename); if(dib.pdata == NULL) return 0;
glGenTextures(1,&texture); glBindTexture(GL_TEXTURE_2D,texture);
SetTexAlpha(color,alpha,dib,r);
{ glTexImage2D( GL_TEXTURE_2D,0,4,dib.width,dib.height,0,GL_RGBA,GL_UNSIGNED_BYTE,dib.pdata); }
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_REPEAT); glEnable(GL_TEXTURE_2D);
FreeDibTexData(dib);
return texture;
} extern "C" GLuint BuildTextureFromImage(unsigned char* image,IMAGESIZE size) { GLuint texture; glGenTextures(1,&texture); glBindTexture(GL_TEXTURE_2D,texture);
if(size.bits == 32) { glTexImage2D( GL_TEXTURE_2D,0,4,size.width,size.height,0,GL_RGBA,GL_UNSIGNED_BYTE,image); } if(size.bits == 24) { glTexImage2D( GL_TEXTURE_2D,0,4,size.width,size.height,0,GL_RGB,GL_UNSIGNED_BYTE,image); } glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_REPEAT); glEnable(GL_TEXTURE_2D);
return texture; }
extern "C" GLuint BuildTextureFromRGBImage(unsigned char* image,IMAGESIZE size) { GLuint texture; glGenTextures(1,&texture); glBindTexture(GL_TEXTURE_2D,texture);
if(size.bits == 32) { glTexImage2D( GL_TEXTURE_2D,0,4,size.width,size.height,0,GL_RGBA,GL_UNSIGNED_BYTE,image); } if(size.bits == 24) { glTexImage2D( GL_TEXTURE_2D,0,4,size.width,size.height,0,GL_RGB,GL_UNSIGNED_BYTE,image); } glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T, GL_REPEAT); glEnable(GL_TEXTURE_2D);
return texture; }
/*************************************************************** 检测一个数是不是 2 的 几 次方 输入: n 为待检测的数字 输出: 0 为 不是2的平方数。 1 为 是一个2的平方数 ***************************************************************/ extern "C" int IsPowerOfTwo(int n) { return !( (( n - 1)& n ) != 0); }
/************************************************************** 调整一个数到能被 4 整除 **************************************************************/ extern "C" int RoundFourByte(int n) { if ( ( n%4)==0 ) return n; else return (n+ 4-(n%4)); }
extern "C" unsigned char* LoadBlankImage(IMAGESIZE size) { if(size.bits != 24 && size.bits != 32) return NULL; int b_len = size.height * size.width * size.bits / 8;
unsigned char* pData = new unsigned char[b_len]; memset((void*)pData,0,b_len); if(size.bits == 32) { for(int i = 0;i<b_len;i+=4) pData[i+3] = 255; } return pData; }
extern "C" int SetImagePixel(unsigned char* image,int x,int y,IMAGESIZE size,unsigned char cl[4]) { if(image == NULL) return 0; int bpp = size.bits / 8; unsigned char* pixel = & image[bpp * size.width * y + x * bpp];
if(bpp == 3) { pixel[0] = cl[0]; pixel[1] = cl[1]; pixel[2] = cl[2]; return 1; } if(bpp == 4) { pixel[0] = cl[0]; pixel[1] = cl[1]; pixel[2] = cl[2]; pixel[3] = cl[3]; return 1; } return 0; }
extern "C" int GetImagePixel(unsigned char* image,int x,int y,IMAGESIZE size,unsigned char cl[4]) { if(image == NULL) return 0;
int bpp = size.bits / 8; unsigned char* pixel = & image[bpp * size.width * y + x * bpp];
if(bpp == 3) { cl[0] = pixel[0]; cl[1] = pixel[1]; cl[2] = pixel[2]; return 1; } if(bpp == 4) { cl[0] = pixel[0]; cl[1] = pixel[1]; cl[2] = pixel[2]; cl[3] = pixel[3]; return 1; } return 0; } extern "C" void SetKeyColorAlpha(unsigned char* image,IMAGESIZE size,unsigned char cl[4],int r) {
if(image == NULL) return ;
for(int y =0 ; y<size.height;y++) for(int x = 0; x < size.width ; x++) { unsigned char* pixel = & image[4 * size.width * y + x * 4]; if( abs(cl[0] - pixel[0]) <= r && abs(cl[1] - pixel[1]) <= r && abs(cl[2] - pixel[2]) <= r ) pixel[3] = cl[3]; } }
void FreeImageData(unsigned char* pData) { if(pData) delete []pData; }

|