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;
}