CImg – a template based image processing lib – read source, not manuals!…

If you are doing image processing on non-standard hardware, you’re probably cross-compiling, or at least cross-developing. I, for myself, am writing image processing algorithms in almost “pure” C/C++ (I know the distinction, and am deliberately using that / to signify that I’m using non-Ansi C with some C++ methods, but seldom library functions), and porting that. And to do that, I like having something that displays images, implements basic functions (every lib has to have something like a kernel..), and is not too complicated. (OpenCV serves that purpose well, but it requires installation, and is a bit too high-level for porting for me).

CImg.h is a header-only library project managed by David Tschumperle. I’m usually not too fond of libraries where everything is in the header, and the repressed compiler warnings irritate me somewhat, but this is not for production, but for testing and quick-and-dirty-coding. And I like this library. It’s easy to understand, mostly well-documented and they provide exactly what I need.
They are dual-licenced with CeCILL C+2(GNU compatible), but to avoid any inaccuracies, just read it up on their website. ( http://cimg.sourceforge.net )

To get started, copy the file into your sources folder, and do

#include "CImg.h"
using namespace cimg_library;

(One of the things I really like is that I don’t have to change any make files, install anything, consider x86/64b,… – it’s doing a great job at keeping this simple).

Even if it’s tempting later on, don’t use using namespace cimg_library::cimg; – they are using loads of std-lib-names!

Opening a file goes like this:

CImg<int> image("test.bmp");

CImg is template based, that is, you can open files as ints or shorts, or bools, or doubles or whatever, as long as it makes sense.

Search the code for “Definition of the CImg<T> structure”, everything is explained there 🙂
You can call the constructor with file-names, c-style arrays or even empty (with parameters like width and heigth).

According to them, the most important things to know about CImg is a) the operator (), which allows you to access pixels and b) display, which displays images.

From the docu:

CImg<float> img1(100,100), img2(img1), img3(img1); // Declare three 100x100 scalar images with unitialized pixel values.
 img1 = "0,50,100,150,200,250,200,150,100,50"; // Set pixel values of 'img1' from a value sequence.
 img2 = "10*((x*y)%25)"; // Set pixel values of 'img2' from a formula.
 img3 = "reference.jpg"; // Set pixel values of 'img3' from a file (image size is modified).
 (img1,img2,img3).display();

They have loads of inplace-copy-add-invert-modulo-AND-XOR-shift-comparison.. operators and functions, so don’t write things that already exist. Then, they are doing operations on channels and colormapping and you can define your own display, which does handle keyboard events, and you can modify them/they are already adapted to your OS. You can also handle mouse-events like scrolling.

Exception handling is done like this: (Copy pasta from source)

#define "CImg.h"
 using namespace cimg_library;
 int main() {
 cimg::exception_mode(0); // Enable quiet exception mode.
 try {
 ... // Here, do what you want to stress the CImg library.
 } catch (CImgException &e) { // You succeeded : something went wrong !
 std::fprintf(stderr,"CImg Library Error : %s",e.what()); // Display your custom error message.
 ... // Do what you want now to save the ship !
 }
 }

And I haven’t even started to mention all the image processing methods!! (And I won’t, at least not in this post).

But I’ve also been looking through the source and found some parts where I wanted to adapt things, the most simple starting with this silly thing:

#define cimg_file_separator '\\'

Why, Windows, why?

I like this comment:

Define 'cimg_use_openmp' to enable OpenMP support.

(and the following code), because I’m a big fan of parallelization and OpenMP is as easy as it gets (well, there’s nothing easy about good parallelization, but OMP makes it look easy)

Also, untested, but sexy:

// OpenCV library may be used to access images from cameras

They support libpng (I tested), libtiff, ffmpeg,Magick++, LAPACK (wow – I got a feeling that someone has once worked in a high-performance environment),.. Nice one!

Reading further through the code, I found that they provide simple macros like:

#define cimg_get2x2(img,x,y,z,c,I,T) \
 I[0] = (T)(img)(x,y,z,c), I[1] = (T)(img)(_n1##x,y,z,c), I[2] = (T)(img)(x,_n1##y,z,c), I[3] = (T)(img)(_n1##x,_n1##y,z,c)

or helper functions like this:

 inline unsigned long tictoc(const bool is_tic) {
 ... //(call "true", later with "false". It will print the elapsed time
They also have a number of math and file-functions as helpers.

Now, this is not for easy porting (unless you define these macros on you own devices), but definitely for qud-testing.

Using adapted versions of libraries can be risky in a team-environment, so a) be careful and do a good job with your version control, b) communicate well and c) remember that at least I am only using this for quick-and-dirty-coding.
They provide the option of defining a namespace-suffix, so you can just force things like:

 using namespace cimg_library_birgit;

Have fun!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: