`

使用DevIL来加载OpenGL纹理

 
阅读更多

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" DIBTEXDATALoadTexData(char* filename);
extern "C" DIBTEXDATACreateDibTexData(int w,int h);
extern "C" voidFreeDibTexData(DIBTEXDATA dib);
extern "C" voidSetTexAlpha(GLubyte color[],GLubyte alpha,DIBTEXDATA dib,int r);
extern "C" voidSetTexPixel(int x,int y,GLubyte color[],DIBTEXDATA dib);
extern "C" voidGetTexPixel(int x,int y,GLubyte color[],DIBTEXDATA dib);
extern "C" GLuintBuildTexture(char* filename);
extern "C" GLuintBuildTransparencyTexture(char* filename,GLubyte color[],GLubyte alpha,int r);
extern "C" GLuintBuildTextureFromImage(unsigned char* image,IMAGESIZE size);
extern "C" GLuintBuildTextureFromRGBImage(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" DIBTEXDATALoadTexData(char* filename);
extern "C" DIBTEXDATACreateDibTexData(int w,int h);
extern "C" voidFreeDibTexData(DIBTEXDATA dib);
extern "C" voidSetTexAlpha(GLubyte color[],GLubyte alpha,DIBTEXDATA dib,int r);
extern "C" voidSetTexPixel(int x,int y,GLubyte color[],DIBTEXDATA dib);
extern "C" voidGetTexPixel(int x,int y,GLubyte color[],DIBTEXDATA dib);
extern "C" GLuintBuildTexture(char* filename);
extern "C" GLuintBuildTransparencyTexture(char* filename,GLubyte color[],GLubyte alpha,int r);
extern "C" GLuintBuildTextureFromImage(unsigned char* image,IMAGESIZE size);
extern "C" GLuintBuildTextureFromRGBImage(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;
}

分享到:
评论

相关推荐

    DevIL 用于opengl加载图片资源

    使用DevIL加载图片资源的步骤大致如下: 1. **初始化DevIL**:调用`ilInit()`函数初始化库。 2. **打开图像文件**:使用`ilLoadImage()`函数加载指定路径的图像文件。 3. **检查加载状态**:通过`ilGetError()`检查...

    立方体 opengl bmp纹理

    在VC++环境中,你可能需要使用如FreeImage、DevIL等库来简化这个过程,但也可以手动实现。一旦有了BMP图像数据,你就可以创建一个OpenGL纹理对象,绑定它,然后使用`glTexImage2D`函数将数据上传到GPU。 在绘制立方...

    基于Assmip,OpenGL直接绘制3D模型到内存DC及透明窗口-WOW希瓦纳斯带纹理

    用Cfree5做的基于 Assimp OpenGL Devil图像库做的3D模型读取...3.Assimp导入,OpenGL的3D模型读取,显示,用DevIL读取纹理进行贴图。 4.Dll的动态加载API函数。 5.拖动可见区域移动窗口。 6.保存HBITMAP到文件的代码。

    易语言源码OPENGL窗口显示外部图片的一般方法.rar

    4. **创建OpenGL纹理** 使用`glGenTextures`生成纹理ID,然后用`glBindTexture`绑定这个ID。接着,通过`glTexImage2D`加载图片数据到纹理。为了优化性能,可以使用`glTexParameter`设置纹理参数,例如过滤模式和...

    MFC+openGL的图片浏览器

    读取图片后,将其加载为OpenGL纹理,这涉及到纹理坐标、纹理参数的设置,以及使用`glTexImage2D`函数将数据上传到GPU。 在图片显示部分,我们将使用OpenGL的绘制函数,如`glBegin`和`glEnd`定义顶点,`glDrawArrays...

    DevIL-Windows-SDK-1.8.0.zip

    2. **API使用**:DevIL提供了一系列的函数接口,如`ilInit()`用于初始化库,`ilLoadImage()`用于加载图像文件,`iluFlipImage()`进行图像翻转,`ilutGLBindTexture()`将图像绑定为OpenGL纹理等。理解这些API的功能和...

    SOIL2-1.3.0.zip

    SOIL2库的使用方法相当直观,它提供了简单的API接口,允许开发者快速将图片数据加载到OpenGL纹理对象中。例如,你可以使用`SOIL_load_OGL_texture()`函数加载一个图像文件,并将其绑定到一个新的OpenGL纹理ID上。...

    dds格式纹理文件

    此外,编程时,也会使用库函数或API,如FreeImage、DevIL、stb_image等,来读取和加载DDS文件到内存中,然后应用到渲染的图形上。 总的来说,DDS格式是图形处理中一个高效且实用的纹理存储解决方案,尤其对于需要...

    SOIL2-master.zip

    我们将 使用 图像 文件 来 向我 们 图形 场景 中的 对象 添加“ 纹理”。 这 意味着 我们 会 需要 频繁 加载 这些 图像 文件 到 我们 的 C++ / OpenGL 代码 中。 从 零 开始 写 一个 纹理 图像 加载 器 是 可能 的。...

    通过MFC编程的方式,采用OpenGL的方法显示BMP格式的图片,采用从图像数据流中装载图像的方法显示JPG格式的图片

    // 将BMP数据加载到OpenGL纹理 // ... } void CShow24bitbmpDlg::OnRender() { // 渲染循环,将BMP图片显示到窗口 // ... } void CShow24bitbmpDlg::OnCleanup() { // 清理OpenGL资源 // ... } ``` 接下来...

    Delphi OpenGL

    学习如何加载纹理(`glGenTextures`、`glTexImage2D`)和应用纹理(`glBindTexture`、`glTexEnvf`)是提高图形质量的关键。 7. **光照和着色**:OpenGL支持多种光照模型,如环境光、漫反射光和镜面光。`glLight`和`...

    mapOpenGL 读取地图的程序

    OpenGL本身并不支持直接读取图像,所以我们通常会使用第三方库如FreeImage或DevIL来完成这个任务。加载的图像数据会被转化为纹理对象,然后绑定到OpenGL的纹理单元上,以便在渲染时使用。 接下来,地图的地理信息...

    OPENGL窗口显示外部图片的一般方法-易语言

    3. **设置OpenGL纹理** OpenGL使用纹理对象来存储图像数据。使用`glGenTextures`生成纹理ID,然后用`glBindTexture`绑定这个ID。接着,通过`glTexImage2D`函数将之前加载的图像数据传入纹理。 4. **设置纹理参数**...

    12-18代码1

    该代码示例主要展示了如何在C++环境中使用OpenCV、OpenGL、GLEW、DevIL以及Assimp库来处理3D模型、图像加载和纹理映射,并涉及到多线程的概念。以下是对这些知识点的详细说明: 1. **OpenCV**: - `opencv2/opencv...

    MFC贴图正方体

    3. **加载贴图**:使用图像处理库(如DevIL或FreeImage)加载外部图像文件作为贴图。这将涉及读取图像数据并将其存储在内存中以便后续使用。 4. **纹理坐标映射**:将加载的贴图映射到正方体的每个面上。每个顶点都...

    stb_image.h及相应cpp

    4. **OpenGL纹理创建**:将图像数据上传到OpenGL纹理对象,这是通过`glTexImage2D`函数完成的。 ```cpp GLuint texture_id; glGenTextures(1, &texture_id); glBindTexture(GL_TEXTURE_2D, texture_id); ...

    double-page.rar_OpenGL_Visual_C++_

    1. **加载纹理**:百頁窗的每一页可能都有不同的图像,所以需要使用OpenGL的纹理映射功能加载和管理这些图像资源。`glGenTextures`函数用于生成纹理ID,`glBindTexture`绑定纹理ID,`glTexImage2D`用于加载纹理数据...

    il.h il_wrap.h ilu.h ilut.h config.h devil_internal_exports.h

    它包含了一些将图像数据上传到OpenGL纹理对象的函数,使得图像可以直接用于图形渲染。ILUT还支持一些与OpenGL交互的实用工具,如自动转换为合适的色彩空间或数据格式。 5. **config.h**: 这个文件通常包含了编译时...

    简单射击游戏代码

    纹理管理涉及到了DevIL库的初始化,DevIL是用于加载和管理图像的库,通过`Il.inInit()`、`Ilu.iluInit()`和`Ilut.ilutTenderer(Ilut.ILUT_OPENGL)`等函数完成纹理加载和OpenGL兼容性配置。 ### 5. 渲染循环 `...

    Developer's Image Library:功能齐全的跨平台图片库-开源

    2. **易于使用**:DevIL的API设计简洁,提供了直观的函数调用来实现图像的加载、保存和转换。例如,使用`ilLoadImage()`函数可以加载图像,`ilSaveImage()`则用于保存图像到指定格式。 3. **图像处理**:DevIL提供...

Global site tag (gtag.js) - Google Analytics