最近學習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(); }
這個樣接口