![]()
|
lena.jpg
, smooth it, display it in a windows, and enter an event loop so that clicking a point in the image will draw the (R,G,B) intensity profiles of the corresponding image line (in another window). Yes, that sounds quite complex for a first code, but don't worry, it will be very simple using the CImg library ! Well, just look at the code below, it does the task :
#include "CImg.h" using namespace cimg_library; int main() { CImg<unsigned char> image("lena.jpg"), visu(500,400,1,3,0); const unsigned char red[] = { 255,0,0 }, green[] = { 0,255,0 }, blue[] = { 0,0,255 }; image.blur(2.5); CImgDisplay main_disp(image,"Click a point"), draw_disp(visu,"Intensity profile"); while (!main_disp.is_closed && !draw_disp.is_closed) { main_disp.wait(); if (main_disp.button && main_disp.mouse_y>=0) { const int y = main_disp.mouse_y; visu.fill(0).draw_graph(image.get_crop(0,y,0,0,image.dimx()-1,y,0,0),red,1,1,0,255,0); visu.draw_graph(image.get_crop(0,y,0,1,image.dimx()-1,y,0,1),green,1,1,0,255,0); visu.draw_graph(image.get_crop(0,y,0,2,image.dimx()-1,y,0,2),blue,1,1,0,255,0).display(draw_disp); } } return 0; }
Here is a screenshot of the resulting program :
And here is the detailled explanation of the source, line by line :
#include "CImg.h"
using namespace cimg_library;
int main() {
CImg<unsigned char> image("lena.jpg"), visu(500,400,1,3,0);
unsigned
char
pixels. The first image image
is initialized by reading an image file from the disk. Here, lena.jpg
must be in the same directory than the current program. Note that you must also have installed the ImageMagick package in order to be able to read JPG images. The second image visu
is initialized as a black color image with dimension dx=500
, dy=400
, dz=1
(here, it is a 2D image, not a 3D one), and dv=3
(each pixel has 3 'vector' channels R,G,B). The last argument in the constructor defines the default value of the pixel values (here 0
, which means that visu
will be initially black). const unsigned char red[] = { 255,0,0 }, green[] = { 0,255,0 }, blue[] = { 0,0,255 };
image.blur(2.5);
get_
). In this case, one could have also written image = image.get_blur(2.5);
(more expensive, since it needs an additional copy operation). CImgDisplay main_disp(image,"Click a point"), draw_disp(visu,"Intensity profile");
while (!main_disp.is_closed && !draw_disp.is_closed) {
main_disp.wait();
main_disp
. if (main_disp.button && main_disp.mouse_y>=0) {
const int y = main_disp.mouse_y;
visu.fill(0).draw_graph(image.get_crop(0,y,0,0,image.dimx()-1,y,0,0),red,1,0,256,0);
fill(0)
simply sets all pixel values with 0 (i.e. clear the image visu
). The interesting thing is that it returns a reference to visu
and then, can be pipelined with the function draw_graph()
which draws a plot in the image visu
. The plot data are given by another image (the first argument of draw_graph()
). In this case, the given image is the red-component of the line y of the original image, retrieved by the function get_crop()
which returns a sub-image of the image image
. Remember that images coordinates are 4D (x,y,z,v) and for color images, the R,G,B channels are respectively given by v=0, v=1
and v=2
. visu.draw_graph(image.get_crop(0,y,0,1,image.dimx()-1,y,0,1),green,1,0,256,0);
visu.draw_graph(image.get_crop(0,y,0,2,image.dimx()-1,y,0,2),blue,1,0,256,0).display(draw_disp);
visu
) is pipelined with the function display()
that just paints the image visu in the corresponding display window. ...till the end
As you have noticed, the CImg library allows to write very small and intuitive code. Note also that this source will perfectly work on Unix and Windows systems. Take also a look to the examples provided in the CImg package ( directory examples/
). It will show you how CImg-based code can be surprisingly small. Moreover, there is surely one example close to what you want to do. A good start will be to look at the file CImg_demo.cpp
which contains small and various examples of what you can do with the CImg Library. All CImg classes are used in this source, and the code can be easily modified to see what happens.