DevIL:Tutorials:Basics

From GPWiki
Jump to: navigation, search

Introduction

The programming interface to DevIL is very similar to the OpenGL one. Here I'll show how to load image and display it using OpenGL. I'll assume that you have DevIL installed already. If you don't then just go to DevIL homepage and install it.

Conventions

The library consists of three sub-libraries:

  • IL - main DevIL library. It allows you to load and save images to files. Every function in this library have 'il' prefixed to their name.
  • ILU - this library contains functions for altering images. Every function in this library have 'ilu' prefixed to their name.
  • ILUT - this library connects DevIL with OpenGL. Every function in this library have 'ilut' prefixed to their name.

Initialization

Before using any DevIL functions (except ilGetInteger(), iluGetInteger(), ilutGetInteger()) you have to call ilInit() to get access to IL library functions, iluInit() to get access to ILU functions and as you probably guessed ilutInit() to get access to ILUT functions. These functions don't return any information about success or failure, so it is good idea to check if DevIL version is newer or equal to the one we are compiling with. To get IL, ILU and ILUT versions we should call ilGetInteger(), iluGetInteger() and ilutGetInteger() with IL_VERSION_NUM, ILU_VERSION_NUM or ILUT_VERSION_NUM as a parameter respectivly. There are IL_VERSION, ILU_VERSION and ILUT_VERSION #defines containing our DevIL libraries versions.

Loading an image

We can load image from a file into system memory using ilLoadImage() function. To do this first we need to generate image name, which is something like a pointer. It points to the image, but we cannot access image data directly through it (it is identical to OpenGL's texture name system). To generate this name we should call ilGenImages() with number of names to generate as first argument and a pointer to ILuint array as second. After this we still can't just load image, because we need to bind image name. To do this call ilBindImage() with image name as parameter. Finally it's time to load image into memory: call ilLoadImage() with file name as a parameter. If everyting went OK this function will return IL_TRUE. Now we can access loaded data using ilGetData() function.

Example

This example shows how to use DevIL inside an OpenGL application. It also uses some SDL basic functions. You don't have to know SDL, but knowledge of OpenGL is required. This code will load and display image.jpg which should be placed in application's directory.

To compile under Linux just type: gcc example.c -lIL -lGL `sdl-config --cflags` `sdl-config --libs`.

To compile under Windows using MSVC you'll need to create new Win32 Application project and add DevIL.lib, OpenGL32.lib, SDLmain.lib and SDL.lib into link section in project's settings.

  1. include <SDL.h>
  2. include <SDL_opengl.h>
  3. include <SDL_main.h>
  4. include <IL/il.h>
  5. include <GL/gl.h>

int main() {

 SDL_Event event;
 ILuint texid; /* ILuint is a 32bit unsigned integer.
   Variable texid will be used to store image name. */
 ILboolean success; /* ILboolean is type similar to GLboolean and can equal GL_FALSE (0) or GL_TRUE (1)
   it can have different value (because it's just typedef of unsigned char), but this sould be
   avoided.
   Variable success will be used to determine if some function returned success or failure. */
 GLuint image;
 int finished;
 SDL_Init(SDL_INIT_VIDEO);
 SDL_SetVideoMode(640, 480, 32, SDL_OPENGL | SDL_HWSURFACE);
 glViewport(0, 0, 640, 480);
 glEnable(GL_TEXTURE_2D);
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 glOrtho(0.0, 640.0, 480.0, 0.0, 0.0, 100.0);
 glMatrixMode(GL_MODELVIEW);
 glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
 glClearDepth(0.0f);
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

/* Before calling ilInit() version should be checked. */

 if (ilGetInteger(IL_VERSION_NUM) < IL_VERSION)
 {
   /* wrong DevIL version */
   SDL_Quit();
   return -1;
 }
 ilInit(); /* Initialization of DevIL */
 ilGenImages(1, &texid); /* Generation of one image name */
 ilBindImage(texid); /* Binding of image name */
 success = ilLoadImage((const ILstring)filename.c_str()); /* Loading of image "image.jpg" */
 if (success) /* If no error occured: */
 {
   success = ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); /* Convert every colour component into
     unsigned byte. If your image contains alpha channel you can replace IL_RGB with IL_RGBA */
   if (!success)
   {
     /* Error occured */
     SDL_Quit();
     return -1;
   }
   glGenTextures(1, &image); /* Texture name generation */
   glBindTexture(GL_TEXTURE_2D, image); /* Binding of texture name */
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); /* We will use linear
     interpolation for magnification filter */
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); /* We will use linear
     interpolation for minifying filter */
   glTexImage2D(GL_TEXTURE_2D, 0, ilGetInteger(IL_IMAGE_BPP), ilGetInteger(IL_IMAGE_WIDTH),
     ilGetInteger(IL_IMAGE_HEIGHT), 0, ilGetInteger(IL_IMAGE_FORMAT), GL_UNSIGNED_BYTE,
     ilGetData()); /* Texture specification */
 }
 else
 {
   /* Error occured */
   SDL_Quit();
   return -1;
 }
 ilDeleteImages(1, &texid); /* Because we have already copied image data into texture data
   we can release memory used by image. */
 /* Main loop */
 finished = 0;
 while (!finished)
 {
   while (SDL_PollEvent(&event))
   {
     switch (event.type)
     {
       case SDL_KEYDOWN:
         if (event.key.keysym.sym == SDLK_ESCAPE)
           finished = 1;
         break;
       case SDL_QUIT:
         finished = 1;
         break;
     }
   }
   /* Draw a quad */
   glBegin(GL_QUADS);
   glTexCoord2i(0, 0); glVertex2i(0,   0);
   glTexCoord2i(0, 1); glVertex2i(0,   480);
   glTexCoord2i(1, 1); glVertex2i(640, 480);
   glTexCoord2i(1, 0); glVertex2i(640, 0);
   glEnd();
   SDL_GL_SwapBuffers();
 }
 glDeleteTextures(1, &image);
 SDL_Quit();
 return 0;

}