最近学习DevIL,一个比较不错的载入多种图片软件。咱们在学习界面的时候,经常须要对这种那种图片格式进行解码,同时在这方面也有许多解决方案,例如独立的cxImage、libpng、libjpeg、freeimage、FFmpeg、SOIL;或者嵌入到别的软件的例如Qt、DirectX。网上说cxImage不错,很多教材使用着一个库,可是cxImage只能在VisualStudio编译(应该能够移植吧,不知道有没有高手作到了,有时间确定要研究一下),并且在VisualStudio编译配置还比较困难,再者cxImage已经中止更新了;SOIL......洗洗睡吧,连tga都载入不了;Qt也有解码多种图片的方案,可是离开了Qt就干不了了;至于FFmpeg,学过用FFmpeg解码音频的读者应该知道有多麻烦,直接使用确定很差用,并且大部分状况应该不会搞得那么细吧。总之,DevIL是一个比较不错的API,尤为对于学过OpenGL的读者,对它的风格会感到很亲切。ios
我大概的学习了一下,发现问题在于全面的资料实在很难找,没有像样的官方资料,若是要深刻的了解着一个软件,以适应各类实际运用的需求,例如控制图片原点位置的功能,按理说DevIL应该有,可是官方文档并无介绍,那么应该找到它的参考文档,通过了我不懈的努力,终于找到了一个详细介绍其API的网站:http://www-f9.ijs.si/~matevz/docs/DevIL,虽然网页依然很慢,但对于使用这一API的我已经很足够了。学习
下面介绍如下DevIL:网站
DevIL原名为OpenIL,不过在SGI要求下,变为了DevIL(其实仍是跟Linux-Devil冲突......)。这是一个强大的图形处理软件,能够载入导出多种格式(20多种,有一些仍是第一次见面)图片、图像处理(ILU模块、好比滤波)、与其余图形库配合使用(ILUT模块,例如与OpenGL、DirectX配合)。并且器接口风格与OpenGL极其相似,使用起来就像OpenGL的一个扩展。在大多数Linux发行版中均可以看见。在apt中软件名称为libdevil-dev。ui
下面介绍一下基本使用方法。spa
#include <IL/il.h> #include <iostream> #include <cassert> int main(){ ILuint image; ILint width,height,type,format; ilInit(); ilGenImages(1,&image); ilBindImage(image); assert(ilLoadImage("test.jpg")); ilGetIntegerv(IL_IMAGE_WIDTH,&width); ilGetIntegerv(IL_IMAGE_HEIGHT,&height); ilGetIntegerv(IL_IMAGE_TYPE,&type); ilGetIntegerv(IL_IMAGE_FORMAT,&format); cerr<<"Image Width:"<<width<<"\nImage Height:"<<height<<"\n"; cerr<<"Image Type:"; switch (format){ case IL_RGB:cerr<<"RGB";break; case IL_RGBA:cerr<<"RGBA";break; case IL_BGR:cerr<<"BGR";break; case IL_BGRA:cerr<<"BGRA";break; case IL_COLOR_INDEX:cerr<<"Color Index";break; default:cerr<<"Other";break; } cerr<<"\nImage Type:"; switch (type){ case IL_UNSIGNED_BYTE:cerr<<"Unsigned Byte";break; case IL_BYTE:cerr<<"Byte";break; case IL_UNSIGNED_SHORT:cerr<<"UNisgned Short";break; case IL_SHORT:cerr<<"Short";break; case IL_UNSIGNED_INT:cerr<<"Unsigned Int";break; case IL_INT:cerr<<"Int";break; case IL_FLOAT:cerr<<"FLoat";break; case IL_DOUBLE:cerr<<"Double";break; default:cerr<<"Other";break; } cerr<<"\n"; void * data=ilGetData(); //载入data...... ilBindImage(0); ilDeleteImges(1,&image); ilShutDown(); }
学过OpenGL纹理的读者应该知道,载入的纹理有可能原点跟OpenGL设定的(在左下角)不符,能够这样设置,就不用担忧这个问题了:code
ilEnable(IL_ORIGIN_SET); ilOriginFunc(IL_ORIGIN_LOWER_LEFT);//or IL_ORIGIN_UPPER_LEFT
能够经过ilSetWrite、ilSetRead控制文件输出输入,在游戏开发里面颇有用,下面给一个嵌入PHYSFS的例子:orm
#include <physfs.h> #include <IL/il.h> #include <cassert> #include <iostream> #include <string> ILint PHYSFS_getc(PHYSFS_File * file){ if (!PHYSFS_eof(file)){ char ch; PHYSFS_read(file,&ch,sizeof(char),1); return ch; } return 0; } ILint PHYSFS_putc(ILubyte ch,PHYSFS_File * file){ return PHYSFS_write(file,&ch,sizeof(ILubyte),1); } ILint PHYSFS_cread(void * buffer,ILint objSize,ILint objCount,PHYSFS_File * file){ return PHYSFS_read(file,buffer,objSize,objCount); } ILint PHYSFS_cwrite(void * buffer,ILint objSize,ILint objCount,PHYSFS_File * file){ return PHYSFS_write(file,buffer,objSize,objCount); } ILint PHYSFS_cseek(PHYSFS_File * file,ILint offset,ILint flag){ PHYSFS_sint64 length=PHYSFS_fileLength(file); PHYSFS_sint64 pos=0; switch (flag){ case IL_SEEK_SET:pos=0;break; case IL_SEEK_CUR:return (ILint)PHYSFS_tell(file); case IL_SEEK_END:pos=length;break; } return PHYSFS_seek(file,pos); } int main(int argc,char * argv[]){ using namespace std; ilInit(); PHYSFS_init(argv[0]); PHYSFS_addToSearchPath(".",true); PHYSFS_setWriteDir("."); ilSetRead( (fOpenRProc)PHYSFS_openRead, (fCloseRProc)PHYSFS_close, (fEofProc)PHYSFS_eof, (fGetcProc)PHYSFS_getc, (fReadProc)PHYSFS_cread, (fSeekRProc)PHYSFS_cseek, (fTellRProc)PHYSFS_tell); ilSetWrite( (fOpenWProc)PHYSFS_openWrite, (fCloseWProc)PHYSFS_close, (fPutcProc)PHYSFS_putc, (fSeekWProc)PHYSFS_cseek, (fTellRProc)PHYSFS_tell, (fWriteProc)PHYSFS_cwrite); ILuint image; ilGenImages(1,&image); ilBindImage(image); assert(ilLoadImage("src.jpg")); ilSaveImage("dst.jpg"); ilBindImage(0); ilDeleteImages(1,&image); PHYSFS_deinit(); ilShutDown(); }
这个样接口