Графика с GDI+

Многие поколения разработчиков и пользователей Windows-приложений привыкли думать о поддержке графического интерфейса как о чём-то само собой разумеющемся. И в этом нет ничего противоестественного: сама задумка этой ОС подразумевает наличие графического интерфейса пользователя, что видно даже из её названия. И, стоит признать, что графический интерфейс Windows - одно из самых больших достижений корпорации Microsoft.

Основная часть графики в Windows обеспечивается графической подсистемой GDI (Graphic Device Interface - в переводе на русский язык, интерфейс графических устройств). Первоначально GDI задумывался корпорацией Microsoft как библиотека для взаимодействия с графическими устройствами, которая прилагалась бы к их продуктам Quick C, Quick Pascal и Quick Basic. В ту славную пору, когда редмондский гигант ещё не был самой большой из ныне существующих компьютерных корпораций, подобными библиотеками сопровождался каждый компилятор. Как выяснилось впоследствии, GDI идеально подходила для операционной системы нового поколения, которую разрабатывала корпорация Microsoft и которая стала известна под именем Windows. Таким образом, до сегодняшнего дня в основу графического ядра Windows входит библиотека, первая версия которой появилась около двадцати лет назад. Этим, в общем-то, и объясняется невысокая скорость работы GDI-графики. В примерах к другой графической библиотеке OpenGL есть программа, демонстрирующая вывод на окно около миллиона точек средствами GDI и OpenGL. В среднем, даже на тех компьютерах, у которых нет 3D-ускорителя, скорость вывода с помощью OpenGL в три-четыре раза больше скорости GDI. На компьютерах, имеющих видеокарту с поддержкой OpenGL, разрыв составляет почти пятнадцать раз. Впрочем, нельзя сказать, что корпорация Microsoft не делает ничего, чтобы ускорить графику в Windows. Как известно, у Windows Vista будет принципиально новая графическая оболочка Avalon. Но уже в системах Windows 2000, XP и 2003 Server (как в 32-битной, так и в 64-битной версиях) используется потомок классической GDI - библиотека CGI+. Впрочем, использовать GDI+ можно и под более ранними версиями систем Windows, но не на уровне всей системы, в целом, а в качестве дополнительной библиотеки в прикладных приложениях. Для этого вместе с самой программой нужно будет распространять GDIPlus.dll размером около одного мегабайта.

Нельзя сказать, что данное нововведение в корне исправляет ситуацию - до скорости OpenGL и DirectDraw стандартной графической подсистеме, конечно же, далеко. Поэтому не нужно думать, что в Windows XP можно полностью отказаться от использования DirectX - это не так; к кому же DirectX отвечает не только за графику. Гораздо полезнее другие возможности GDI+, которые дают значительно больше инструментов в руки разработчика. Именно о них мы сейчас и поговорим.

Во-первых, GDI+ предоставляет возможность разработчикам, использующим C++, не возиться с дескрипторами (handles), а использовать классы. Те, кто хоть раз писал дескриптор-ориентированное приложение размером более тысячи строк исходного кода, поймут прелесть объектно-ориентированного подхода. Причём обратите внимание, что эти классы не просто чья-то сторонняя обёртка над GDI+ - их предлагает сама корпорация Microsoft. Заголовочные файлы для GDI+ входят в поставку последних версий Visual C++ и C++ Builder, а тем, кто использует какое-то другое средство разработки на C++, придётся взять их из Microsoft Platform SDK. К сожалению, эта замечательная особенность GDI+ вряд ли пригодится тем, кто использует языки программирования, отличные от C++.

Библиотека GDI, долгие годы правившая бал в области графики под Windows, позволяет проводить только весьма простые операции с графикой: рисовать геометрические примитивы, копировать области участков экрана, масштабировать изображения, работать с форматами BMP, WMF, EMF и ICO. Библиотека GDI+ представляет более широкие возможности работы с графикой под Windows. Сейчас я расскажу об основных из них.

Первой из непосредственно графических возможностей CGI+, которую хотелось бы отметить, является встроенная поддержка градиентной заливки. Хотя этот вопрос неоднократно освещался в различных статьях, сборниках ответов на часто задаваемые вопросы и на форумах, всё равно количество жаждущих приобщиться к градиенту не уменьшается. Теперь можно забыть о кодировании несложного, в общем-то, алгоритма - GDI+ сделает такую заливку за вас. Заливать можно в разных направлениях и, естественно, любыми цветами, можно даже не заливать, а рисовать градиентные линии.

Кстати, о линиях: GDI+, в отличие от простого GDI, поддерживает отрисовку фундаментальных сплайнов (cardinal splines). Фундаментальный сплайн - кривая, полученная путём сглаживания ломаной, получаемой при проведении отрезков между ближайшими пунктами массива точек. Впрочем, стоит отметить, что GDI+ поддерживает и обратную операцию - построение ломаной по соединённым кривым Безье.

Имеется возможность трансформации объектов. Преобразования производятся в матричной форме: для преобразования (поворота или увеличения) нужно сначала создать специальный объект-матрицу и заполнить её соответствующими коэффициентами трансформации. В целом, задача эта не такая уж сложная, хотя требующая некоторых базовых знаний из области аналитической геометрии и алгебры матриц. Результаты преобразования сохраняются в объекте, так что возможно применение последовательных трансформаций.

Результатом применения GDI+ в операционных системах Windows 2000, XP и 2003 Server стала возможность использования альфа-прозрачности при выводе графических объектов на экран. В Windows 2000 это использовалось лишь при выводе на экран меню: эффект его появления и исчезания реализован с использованием альфа-прозрачности. В Windows XP этот эффект используется гораздо шире: даже значки на рабочем столе используют цветовой альфа-канал, а общее количество "украшений", основанных на использовании альфа-прозрачности, намного превышает их скромное число в предыдущей версии Windows. Помимо альфа-прозрачности, поддерживается ещё одно средство придания картинкам большей привлекательности - сглаживание (по-английски это звучит как anti-aliasing). Приём сглаживания основан на том, что пикселы, соседствующие с краем геометрической фигуры или картинки, окрашиваются в цвета, промежуточные между цветами фона и цветом фигуры, за счёт чего края визуально сглаживаются и смотрятся на экране более красиво.

Актуальной является поддержка работы с разными форматами растровых и векторных изображений. Что это значит? Это значит, что с помощью GDI+ стало возможным загружать, сохранять и отображать картинки не только в формате BMP, ICO или WMF и EMF, но также и GIF (в том числе и с анимацией), JPEG, Exif, PNG, TIFF. Это должно особенно порадовать разработчиков приложений, где предусмотрена работа с различными графическими форматами. Конечно, это не совсем то, на что способен великий и могучий Photoshop, но уже не нужно самостоятельно писать обработку разных форматов или добиваться совместимости между классами для работы с каждым из них. Хотя остаётся непонятным один вопрос. Дело в том, что схема компрессии LZW, используемая в GIF, запатентована корпорацией Unisys, а потому для использования этого формата в своих приложениях разработчики должны перечислять на счёт корпорации лицензионные отчисления. Что касается ситуации с GDI+, то возникает неоднозначность - вроде бы, GIF использует не само приложение непосредственно, а библиотеку GDI+, но Microsoft вряд ли согласилась заплатить Unisys'у за всех разработчиков сразу. Сам компьютерный гигант по этому поводу нем как рыба.

Теперь нужно, как мне кажется, сказать несколько слов о классах, лежащих в основе GDI+, и об их иерархии. Примеров использования GDI+ в этой статье не будет, т.к. объём газетной статьи, к сожалению, ограничен, но я не исключаю возможности появления продолжения, уже с примерами. Так что сейчас мы с вами только перечислим основные классы GDI+ и их назначение, чтобы вы могли с ними при желании поэкспериментировать.

Базовым классом для всех остальных является класс GdiplusBase, и, коль скоро он просто базовый, достаточно просто знать, что он есть. Этот класс наследуют классы Brush, CachedBitmap, Graphics, GraphicsPath, GraphicsPathIterator, Font, Image, ImageAttributes, Matrix, Pen, Region и некоторые другие. Brush - это кисть, которая используется для рисования графических примитивов с заливкой. У этого класса есть наследники, отвечающие за отрисовку данного конкретного вида заливки (градиентной, равномерной, текстурной или с каким-либо простым геометрическим узором). CachedBitmap - класс для хранения растрового изображения в памяти и для его отрисовки на экране. Graphics - один из основных, пожалуй, классов, который используется для вывода на экран всех графических объектов. Именно с ним приходится чаще всего иметь дело программисту. Класс GraphicsPath используется для хранения и отрисовки целого ряда прямых, кривых или геометрических фигур. GraphicsPathIterator - вспомогательный класс для предыдущего класса, с его помощью можно манипулировать группами объектов в рамках класса GraphicsPath. Font - как вы, может быть, уже догадались, класс для работы со шрифтами. Image - класс для работы с изображениями; именно он отвечает за их загрузку, сохранение, а также позволяет ими манипулировать. ImageAttributes - особый класс для работы с атрибутами изображения, используется тоже довольно часто. Matrix - класс для матричных преобразований, о которых я уже немного рассказал выше. Pen - виртуальное перо, рисующее линии и геометрические примитивы. Region - класс, описывающий какой-либо участок экрана произвольной формы. Этот класс используется при побитовом копировании и других битовых операциях. Это, конечно, далеко не все классы, использующиеся в библиотеке GDI+, но, я думаю, на первых порах их хватит.

Напоследок сообщу о неожиданно обнаруженной возможности использования GDI+ для Delphi-программистов. По адресу www.progdigy.com можно найти модули для работы с GDI+ на Delphi.

Таким образом, подведём резюме: GDI+ - следующее поколение библиотеки GDI, обладающее рядом полезных возможностей и имеющее объектно-ориентированную структуру. Конечно, GDI+ - не DirectX, но в "офисных" программах его применение может дать положительный эффект в плане внешнего вида интерфейса приложения. Обязательно попробуйте поэкспериментировать с GDI+ - это действительно интересная и полезная библиотека.

Вадим СТАНКЕВИЧ

Версия для печатиВерсия для печати

Номер: 

22 за 2006 год

Рубрика: 

Software
Заметили ошибку? Выделите ее мышкой и нажмите Ctrl+Enter!

Комментарии

Страницы

Аватар пользователя Emulator
А где выводы о скорости прорисовки GDI+? Есть намек что новая версия быстрее, а где факты?
Аватар пользователя Вадим Станкевич
Честно говоря, не проверял, но MS пишет, что "Speed impoved a bit". Я думаю, такой большой фирме можно верить.
Аватар пользователя wsd
Все это хорошо но: градиентную заливку, кривые Безье, трансформация объектов согласно матрице, альфа прозрачность, загрузку JPEG, Exif, PNG, TIFF можно сделать и средствами обычного GDI (за исключением загрузки картинок, что делается например используя IImgCtx или OleLoadPicture).

Так что GDI+ - это просто обертка над уже готовыми функциями GDI.

Аватар пользователя wsd
Повеселило насчет больше 1000 строчек. Да... 1000 строк это ж мега прога :)
Аватар пользователя Вадим Станкевич
1000 строчек - это уже достаточно, чтобы запутаться в handle'ах. Что касается функций GDI ("градиентную заливку, кривые Безье, трансформация объектов согласно матрице, альфа прозрачность, загрузку JPEG, Exif, PNG, TIFF можно сделать и средствами обычного GDI"): это не работает под Win98 (проверено). Так что GDI+ - больше чем просто обёртка.
Аватар пользователя wsd
//1000 строчек - это уже достаточно, чтобы запутаться в handle'ах.

кому как ;)

GradientFill, AlphaBlend есть начиная в виндах с 98 (а вы думаете заголовки окон стали градиентом заливаться через GDI+, в ядре то ;))

PolyBezier есть начиная с 95.

OleLoadPicture есть так же в 95. IImgCtx интерфейс от винды вообще не зависящий. Он ставится не то с 4м не то с 5м IE.

Аватар пользователя wsd
Ой, надеюсь вы не перепутали альфаблендинг операций с изображениями с альфа бленлингом layered-окон (тем самым что в делфи несколькими свойствами регулируется) который не имеет отношения ни к GDI ни к GDI+, и который присутствует в 2k и выше? ;)
Аватар пользователя Вадим Станкевич
И как это альфа-блендинг окон не имеет ни к GDI, ни к GDI+ никакого отношения?
Аватар пользователя Вадим Станкевич
Кстати, 1000 строчек (чужих) - пример из жизни (моей).
Аватар пользователя wsd
Объясню популярно на примере NT систем: userspace dll'ки gdi32.dll/user32.dll являются "мордами" керненовского гхм.. драйвера.. win32k.sys и процесса csrss.exe. DefWindowProc и рендеринг девайс контекстов происходят в ядре, в котором и не пахнет gdiplus.dll, являющейся полностью userspace модулем без какой-либо особенной поддержки со стороны ядра. А вот рендерингом полупрозрачных LAYERED окон занимается по большей части уже скорее драйвер видеокарты. Т.к. при этом контекст окна отображается не в общий скринбуфер, а в отдельный буфер (при возможности - в видеопамяти), который накладывается с альфаблендингом на экран уже драйвером видеокарты (аппаратно или прозрачность эмулируется драйвером).

В случае API вызова AlphaBlend под NT (из msimg32.dll) всю работу проводит недокументированный вызов GdiAlphaBlend из GDI32.dll который уходит в ядро. Под 98 AlphaBlend в ядре не реализован. Он реализован в самой msimg32.dll. Потому рисовать полупрозрачные картинки на DC через API мона, а делать окна полупрозрачными - нет.

Затруднились бы заглянуть в MSDN по поводу этих функций. Там все прекрасно написано (если читать до конца) под какими виндами они есть, а под какими их нет.

Страницы