The task of using DevIL may seem daunting at first, with the multitudes
of functions available, but DevIL is actually relatively easy to use.
This tutorial will show you how to create a simple DevIL application
to load, save and display a variety of images.
Checking Versions
This is a critical first step for any well-written application that
utilizes DevIL. With almost all compilers supported, DevIL is
generated as a shared library. Even though the function names may
all be the same, earlier versions of DevIL may have inconsistencies
that render your application unuseable. Bugfixes are constantly
introduced to try to make DevIL the best image library ever.
The drawback to shared libraries is that a user may inadvertently
(or purposefully) replace a newer version of DevIL with an older
version than your application was designed for. Luckily, DevIL
provides version mechanisms to check versions --
ilGetInteger,
iluGetInteger and
ilutGetInteger. There are
#defines in all three libraries that provide the version number your
application was compiled with to check against the version number
returned by their respective GetInteger functions:
IL_VERSION, ILU_VERSION and ILUT_VERSION.
Example of version checking.
if (ilGetInteger(IL_VERSION_NUM) < IL_VERSION ||
iluGetInteger(ILU_VERSION_NUM) < ILU_VERSION)
ilutGetInteger(ILUT_VERSION_NUM) < ILUT_VERSION) {
printf("DevIL version is different...exiting!\n");
return 1;
}
Initializing the Library
With compilers that support shared libraries, no initialization is
required, as DevIL is automatically intialized when it is loaded by
an application. Initialization is recommended, though, to ease any
porting troubles. Plus, it is only one additional line of source.
All that is needed to initialize DevIL is to call
ilInit. No
parameters are even needed.
Image Names
DevIL's image name system is virtually identical to OpenGL's texture
name system. First, you need an image name variable:
ILuint ImageName;
Next, generate an image name to be put in this variable:
ilGenImages(1, &ImageName);
Now bind this image name so that DevIL performs all subsequent operations on this image:
ilBindImage(ImageName);
Creating images is as simple as that. No messy pointers or anything else
to mess with. To get an in-depth explanation of image names, read
the tutorial on them.
Loading an Image
Loading an image is as simple as it can be with DevIL. For most programs,
a simple call to ilLoadImage will suffice. IF the image was not loaded
due to any of various reasons, ilLoadImage returns false, else it returns
true if the image was successfully loaded.
Code for loading an image.
ilLoadImage("monkey.tga");
Saving an Image
Saving an image is just as easy as loading an image via DevIL. Just
call ilSaveImage with the desired filename as the only parameter. If
DevIL could not save the image, ilSaveImage returns false, else it
returns true. By default, DevIL will refuse to overwrite any images
that already exist on the harddrive to prevent from overwriting important
data. To change this behaviour to allow overwriting of files, use
ilEnable with the IL_FILE_OVERWRITE parameter.
Code for saving an image.
ilEnable(IL_FILE_OVERWRITE);
ilSaveImage("llama.jpg");
Checking for Errors
Occassionally, errors may occur in DevIL, such as an image not being loaded.
If an DevIL function returns indicating an error (e.g. returns false from
a function that returns an ILboolean), an error code is set internally in
DevIL and may be retrieved via ilGetError.
Usually, the code is quite specific about what kind of error occurred.
DevIL maintains an error stack (usually 32 errors deep) so that if more
than one error is set, an error doesn't get "lost". When you call ilGetError,
the last error set is popped off of the stack. If no error has occurred, or
all the errors have been popped off of the stack, ilGetError returns IL_NO_ERROR.
For a more in-depth discussion of errors, read
the tutorial on them.
Code for detecting an error.
ILenum Error;
Error = ilGetError();
Image Information
Of course DevIL would be pretty useless if you could not retrieve information
about the image somehow. ilGetInteger
serves this purpose very well, allowing you to know pretty much everything about
an image. Some useful values to pass as parameters to ilGetInteger are
IL_IMAGE_WIDTH, IL_IMAGE_HEIGHT and IL_IMAGE_BPP. All of these and more are
defined in DevIL's il.h header.
Code for getting an image's width and height.
ILuint Width, Height;
Width = ilGetInteger(IL_IMAGE_WIDTH);
Height = ilGetInteger(IL_IMAGE_HEIGHT);
Image Data
To get a pointer to the image data for your own use, make a call to
ilGetData. ilGetData returns
a direct pointer to the image data. Do not try to free this pointer
when you are done with it, as it does not point to a copy of the image
data but to the actual image data. The image data is freed when you
delete the image.
Code for getting the image data.
ILubyte *Data = ilGetData();
Display the Image
DevIL supports several different APIs for displaying an image through
ilut. Since ilut is separate from il, you could manually send data to
the API just as ilut does, though it would require more code and time
from you (same as writing your own image routines =). Right now, we
will only focus on OpenGL though, as DevIL is OpenGL's bastard sibling.
For a much more in-depth discussion of using DevIL with OpenGL, read
this tutorial.
Before you call any ilut functions dealing with OpenGL and after you
have initialized OpenGL, you *must* call
ilutRenderer with the
ILUT_OPENGL parameter to initialize ilut correctly.
Most applications will then only need to call
ilutGLBindTexImage to get a
corresponding OpenGL texture from the DevIL image. If you only need
to use the OpenGL texture and not the DevIL image after this, it is
safe to delete the image.
Example of getting an OpenGL texture.
GLuint Texture;
Texture = ilutGLBindTexImage().
Deleting an Image
To delete an image when you are through with it, call
ilDeleteImages. ilDeleteImages
frees all data and makes that image name available for use in the future.
ilDeleteImages has a syntax exactly like ilGenImages, and the functions
are each other's complement.
Example of deleting an image.
ilDeleteImages(1, &ImageName);