Image Manipulation With CImg

by Pandafox | Posted in cpp, Tutorials

Experimenting with image manipulation with c++ can be quite cumbersome if you don’t take advantage of existing libraries. Just loading a JPEG image, applying some filter and then displaying it in a window could easily require more than fifty lines of boilerplate code. With a library like CImg, this can easily be done in less than ten lines, like so:

#include "CImg.h"
using namespace cimg_library;
int main () {
    CImg<unsigned char> img("photo.jpg");
    (img, img.get_blur(8)).display("Hello, CImg!");
    return 0;
}

This piece of code loads the image “photo.jpg” into a CImg instance and displays it inside a window, along with a blurred version of the image, like so:


Blur with cimg

Also notice that the code only includes 1 header file, “CImg.h”. The whole CImg library is actually contained in one single, massive, header file. This does increase the compile time, but then again, it’s really, really simple.

Compiling

The CImg documentation provides information on how to compile CImg on various platforms, but long story short, this is how to compile a simple CImg program on some of the most common platforms:

g++ on Linux

g++ -o hello hello.cpp -O2 -L/usr/X11R6/lib -lm -lpthread -lX11

g++ on Mac OS X

g++ -o hello hello.cpp -O2 -lm -lpthread -L/usr/X11R6/lib -lm -lpthread -lX11

Microsoft Visual C++ 6.0, Visual Studio.NET and Visual Express Edition

Use project files and solution files provided in the CImg Library package (directory ‘compilation/’) to see how it works.

(Pretty much taken straight from the documentation)

And make sure CImg.h is in the same directory as the rest of your source code.

The code

Once you’ve managed to successfully compile and run the aforementioned code, we can take a closer gander at the code.

We start by including CImg.h and declaring that we will be using the cimg_library namespace.

All the CImage classes and functions resides in the cimg_library namespace, which is why we declare that we will be using the this very namespace.

CImage is a template-oriented library, meaning that it is making heavy use of templates to achieve great genericity. So you can pretty much work with any pixel type you want, be it integer, floating-point or boolean datatypes.

In this case, we’re using unsinged char as the datatype for our pixel values.

CImg<unsigned char> img("photo.jpg");

This line loads the image into a new CImg object and the template parameter specifies that we want to use unsigned char as the pixel format.

(img, img.get_blur(8)).display("Hello, CImg!");

In this line, there’s a lot of things going on, but long story short: It creates a CImgList object which contains two images (the original image, and a blurred version of the image). The display-method is called on the CImgList object, which will display the images in a window with the caption, “Hello, CImg!”.

If you just want to show one of the images, just call the display-method on the image object like so:

img.display("Hello, CImg!");

or

img.get_blur(8).display("Hello, CImg!");

Really, that’s all there is to it!

So, whats next?

CImage is, of course, capable of doing other things than blurring images. If you take a look at the CImg< T > Struct Template Reference, you’ll see a full list of filters, transformations and whatnot you can apply to your images. Everything from fourier transformations:

img.get_FFT();

to inverting the colors:

img.get_invert();

Have fun!