Краткое описание библиотеки CImg

Доброго времени суток!

Все время очень сильно привлекала внимание обработка изображений (алгоритмы сжатия, фильтры и т.д.). Увы, сложилось так, что работа практически не связана ни с обработкой изображений, ни с программированием вообще. Тем не менее, интерес к любимому делу не уменьшился и поэтому хочу представить Вашему вниманию недавно открытую для себя библиотеку CImg.

CImg – библиотека C++, предоставляющая классы и функции обработки изображений. Это как элементарные функции (загрузка, сохранение, просмотр), так и алгоритмы для изменения размера/вращения, применения эффектов, отрисовки объектов (текста, линий, поверхностей, элипсов, ...), и т.д.

Структура библиотеки


Библиотека состоит из одного заголовочного файла CImg.h, который включает в себя все классы и функции CImg. В этом отличительная черта библиотеки, в чем есть некоторые плюсы:
  • отсутствие необходимости предварительной компиляции библиотеки, поскольку CImg-код компилируется (извините за тавтологию :-) во время компиляции основной программы, включающей в себя CImg.h;
  • отсутствие сложных зависимостей: просто включаем CImg.h в свой проект;
  • компиляция происходит «на лету»: в исполняемый файл включается только та функциональность, которая используется в программе. Это позволяет создавать очень компактные приложения;
  • члены классов и функции являются встраиваемыми (inlined), что приводит к более высокой производительности во время исполнения программы;

Библиотека CImg имеет следующую структуру:
  • все классы и функции библиотеки определены в пространстве имен cimg_library, которое инкапсулирует в себе всю функциональность библиотеки и позволяет избежать коллизий, которые могут случится при добавлении других заголовочных файлов в проект. Обычно используют только это пространство имен как стандартное:
    	#include "CImg.h"
    	using namespace cimg_library;
    
  • Пространство имен cimg_library::cimg определяет набор низкоуровневых функций и переменных, используемых в библиотеке;
  • Класс cimg_library::CImg<T> — основной класс библиотеки, экземпляры которого представляют сущность (изображение) вплоть до 4-х размерного (начиная от одноразмерного скаляра до 3-х мерных наборов пикселей), с шаблонными типами пикселей;
  • Класс cimg_library::CImgList<T> представляет списки cimg_library::CImg изображений. Он может быть использован, например, для хранения последовательности изображений (кадров, ...);
    Класс cimg_library::CImgDisplay отображает изображения или наборы изображений в графической среде. Можно смело заявить, что код этого класса сильно зависит от системы, но на самом деле это не волнует программиста, т.к. переменные среды устанавливаются автоматически посредством CImg-библиотеки;
    Класс cimg_library::CImgException (и его подклассы) используются библиотекой для обработки исключений при возникновении ошибок. Исключения обрабатываются с помощью try {..} catch (CImgException) {… }. Подклассы позволяют точно определить тип ошибки;

    Знание этих четырех классов достаточно, чтобы в полное мере пользоваться функциональностью CImg-библиотеки.

    Hello, world!


    Ну да ладно, сказано было достаточно много. Рассмотрим лучше наглядный пример того, как работает элементарная программа, написанная с использованием CImg.
    		#include "CImg.h"
    		using namespace cimg_library;
    
    		int main() {
    			CImg<unsigned char> img(640,400,1,3);
    			img.fill(0);
    			unsigned char purple[] = { 255,0,255 };
    			img.draw_text(100,100,"Hello World",purple);
    			img.display("My first CImg code");
    			return 0;
    		}
    		

    Рассмотрим более детально каждую строку программы:

    Подключим заголовочный файл библиотеки CImg
    		#include "CImg.h"
    		

    Будем использовать пространство имен cimg_library, чтобы облегчить объявления типов
    		using namespace cimg_library;
    		

    Объявим главную функцию программы
    		int main() {
    		

    Создадим экземпляр изображения — img, с типом пикселей unsigned char, размера 640*400*1 пикселей (в данном случае 1 говорит о том, что изображение будет плоским, не трехмерным). Каждый пиксель имеет 3 канала — RED, GREEN и BLUE. Об этом говорит последний параметр конструктора.
    		CImg<unsigned char> img(640,400,1,3);
    		

    Закрасим изображение черным цветом («0» означает черный)
    		img.fill(0);
    		

    Объявим переменную purple: она будет цветом
    		unsigned char purple[] = { 255,0,255 };
    		

    Выведем от точки (100,100) на изображении текст «Hello World» цветом purple
    		img.draw_text(100,100,"Hello World",purple);
    		

    Покажем изображение в графическом окне с заголовком «My first CImg code»
    		img.display("My first CImg code");
    		

    Завершим программу
    		return 0;
    		

    Как видно, библиотека CImg достаточна проста в использовании, названия методов интуитивно понятны. Хотя вышеизложенный код можно было записать еще более компактно:
    	#include "CImg.h"
    	using namespace cimg_library;
    
    	int main() {
    		const unsigned char purple[] = { 255,0,255 };
    		CImg<unsigned char>(640,400,1,3,0).draw_text(100,100,"Hello World",purple).display("My first CImg code");
    		return 0;
    	}
    	

    Скриншот (кликабельно):

    Надеюсь, в будущем разберем еще несколько примеров, уже посложнее!
    Сайт проекта: cimg.sourceforge.net
    Благодарю за внимание!


    P.S.
    • В Linux компилируется командой:
      g++ -o hello hello.cpp -O2 -L/usr/X11R6/lib -lm -lpthread -lX11(Можно обойтись и без -O2)
    • Компилируется достаточно долго (Linux Gentoo, Pentium® Dual-Core CPU T4500 @ 2.30GHz):
      $ time g++ -o hello hello.cpp -O2 -L/usr/X11R6/lib -lm -lpthread -lX11
      real 0m28.397s
      user 0m27.991s
      sys 0m0.265s
      28 секунд (!) для Hello, World! не слишком ли? Хотя без "-O2" быстрее в три раза.
    • Размер бинарника составляет 742K что, в общем сопоставимо со временем компиляции!
  • +3
  • 11,8k
  • 9
Поделиться публикацией
Комментарии 9
    +1
    А чем оно лучше imagemagick и Cairo?
      0
      Честно говоря, я не знаю, чем CImg лучше Cairo. Знаю лишь то, что CImg использует imagemagic:
      #ifdef cimg_use_magick
      #include "Magick++.h"
      #endif
      

      Ну и плюс ко всему реализованы функции вывода изображения в окно X11.
        0
        CImg хорошо работает и без imagemagick. Но если вы хотите использовать возможности сторонней библиотеки, то можно это в коде явно указать и потом пользоваться дополнительными функциями (OpenCV, OpenMP, Lapack и проч.)

        +1
        Зачем оно должно быть лучше?

        Не пользовался указанными библиотеками, но в CImg хорошо работать с медицинскими изображениями разных форматов. Лично для меня этот факт оказался важным.
          0
          В Cairo прежде всего упор делается на работу с векторной графикой (1, 2)
            0
            В Cairo можно прекрасно работать с растрами, команда Mono на нём реализовала весь стек GDI+, необходимый для System.Drawing.
            –1
            Чем оно лучше OpenCV?
            0
            Я думаю, стоит отказаться от такого дотошного описания, буквально каждую строчку описывать не стоит, а пример можно было бы взять и посложнее.

          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

          Самое читаемое