IRRLICHT は,もともと C 言語ベースの3次元エンジンです. IRRLICHT は,画像(カラー,モノクロ)の描画、2次元グラフィックス、3次元グラフィックス,イベント処理(マウス,キーボード等)の機能をもったゲームエンジンの決定版です. 文字の描画 (unicodeも可), 画像ファイル読み書きの機能もありますし,スライダやボタンなどのGUI部品もあるので,困ることはありません.
このページではIrrlicht を用いたカラー画像ビューワのプログラム例を示す. 単なるカラー画像ビューワを作りたいのではなくて,ウインドウを開いて画像を表示するようなプログラムを C 言語で簡単に作ることが出来る見本として示している.
RGBのカラー画像ファイルについては,以下のことを仮定している.
なぜ SDL の最新版を使っているのか? 画像ファイルはヘッダが付いていたり,しばしば圧縮されている.画像ファイルの種類もいろいろある.SDL を使うと,こうしたことを気にしなくて済むと考えました.
#include<stdlib.h> #include<stdio.h> #include<string.h> #ifdef WIN32 #include<windows.h> #endif #include<irrlicht.h> using namespace irr; using namespace core; using namespace scene; using namespace video; using namespace io; using namespace gui; #include "SDL.h" #include "SDL_image.h" #pragma comment(lib, "Irrlicht.lib") const int WMAX = 2048; // the width of an image buffer const int HMAX = 2048; // the height of an image buffer static unsigned char tmp_rgb24[3*WMAX*HMAX*2*2]; // buffer. 2の指数乗の大きさに拡張して画像を格納する配列 static video::ITexture* create_slice_texture(int width, int height, unsigned char *r, unsigned char *g, unsigned char *b, video::IVideoDriver* driver) { int i,j; int twidth, theight; //2の指数乗に拡張した画像の大きさ if(width < 64) twidth=64; //twidth, theightの設定 else if(width < 128) twidth=128; else if(width < 256) twidth=256; else if(width < 512) twidth=512; else if(width < 1024) twidth=1024; else twidth=2048; if(height <64) theight=64; else if(height <128) theight=128; else if(height <256) theight=256; else if(height <512) theight=512; else if(height <1024) theight=1024; else theight=2048; // fprintf(stderr, "twidth = %d, theight = %d\n", twidth, theight); for( i=0; i < height; i++ ) { for( j=0; j < width; j++ ) { tmp_rgb24[ i * twidth*3 + (j * 3)] = r[ i * width + j ]; // Blue tmp_rgb24[ i * twidth*3 + (j * 3) + 1] = g[ i * width + j ]; // Green tmp_rgb24[ i * twidth*3 + (j * 3) + 2] = b[ i * width + j ]; // Red } } video::IImage* slice_image = driver->createImageFromData(video::ECF_R8G8B8, core::dimension2d<u32>(twidth,theight), tmp_rgb24, false); video::ITexture* slice_texture = driver->addTexture("tmp_texture", slice_image); slice_image->drop(); return slice_texture; } int main(int argc, char *argv[]) { SDL_Surface *image; int width, height, bpp; int i, j, k; unsigned char *r; unsigned char *g; unsigned char *b; /* Check command line usage */ if ( ! argv[1] ) { fprintf(stderr, "Usage: %s <image_file>\n", argv[0]); return(1); } /* Open the image file */ image = IMG_Load(argv[1]); if ( image == NULL ) { fprintf(stderr, "Couldn't load %s: %s\n", argv[1], SDL_GetError()); } k = 0; width = image->w; height = image->h; bpp = image->format->BytesPerPixel; fprintf( stderr, "bpp = %d\n", bpp ); fprintf( stderr, "width = %d\n", width ); fprintf( stderr, "height = %d\n", height ); r = new unsigned char[width * height]; g = new unsigned char[width * height]; b = new unsigned char[width * height]; for ( i = 0; i < height; i++ ) { for ( j = 0; j < width; j++ ) { // 1画素の R, G, B 成分は1バイトであること.画像データは隙間無くならんでいること.R, G, B の順に並んでいることを仮定している. unsigned char* p = (unsigned char*)image->pixels; long int pixel_at = k * bpp; r[k] = p[pixel_at]; g[k] = p[pixel_at + 1]; b[k] = p[pixel_at + 2]; k++; } } /* SDL 処理終了 */ SDL_Quit(); //ウィンドウを開くなど video::E_DRIVER_TYPE driverType; #ifdef WIN32 driverType = video::EDT_DIRECT3D9; #else /* driverType = video::EDT_OPENGL; */ driverType = video::EDT_SOFTWARE; /* driverType = video::EDT_SOFTWARE2; */ #endif static IrrlichtDevice *device = createDevice( driverType, /* windowSize */ core::dimension2d<u32>(width, height), /* bits */ 16, /* fullscreen */ false, /* stencilbuffer */ false, /* vsync */ false, /* IEventReceiver */ 0 ); if (device == 0) return 1; video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* scenemgr = device->getSceneManager(); gui::IGUIEnvironment* guienv = device->getGUIEnvironment(); gui::IGUIFont* font = guienv->getBuiltInFont(); device->setWindowCaption(L"simple viewer"); //表示部分 video::ITexture* slice_texture = create_slice_texture(width, height, r, g, b, driver); while(device->run() && driver){ if (device->isWindowActive()){ driver->beginScene(true, true, video::SColor(0,120,102,136)); driver->draw2DImage(slice_texture, core::position2d<s32>(/* drawPos_x */ 0, /* drawPos_y */ 0), core::rect<s32>(0,0,width,height), 0, video::SColor(255,255,255,255), true); driver->endScene(); } } driver->removeTexture(slice_texture); device->drop(); delete (r); delete (g); delete (b); return(0); }
【Linux でのビルドコマンド(例)】
g++ -I/usr/include/irrlicht -I/usr/include/SDL -I/usr/include/png12 -o a.out hoge.cc -L/usr/lib64 -lSDL_image -lSDL -lpthread -lm -L/usr/local/lib -lIrrlicht -lGL -lGLU -lXext -lX11
Fedora の場合のコマンド例
g++ -I/usr/include/irrlicht -I/usr/include/SDL -I/usr/include/png12 -o a.out hoge.cc -L/usr/lib64 -lSDL_image -lSDL -lpthread -lm -L/usr/local/lib -lIrrlicht -lGL -lGLU -lXxf86vm -lXext -lX11