Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Полигон
  
 

Фильтр по датам

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
  
 
Во Флориде и в Королевстве сейчас  22:53[Войти] | [Зарегистрироваться]

Альтернатива TGIFImage

Сергей Галездинов
дата публикации 20-01-2009 10:26

Альтернатива TGIFImage

Наверняка многие из нас сталкивались с проблемой: необходимо отобразить в программе некий анимированный объект. Одно из решений — использовать компонент Animate и AVI ролик. Однако найти нужный ролик сложно, да и создать/отредактировать не легче. Второе решение — использовать анимированную графику (коей на данный момент очень много) — и gif тут признанный лидер (хотя, конечно, этот формат не отвечает современным веяниям. В частности никакого альфа-канала и максимум 256 цветная палитра). Есть еще набирающие обороты форматы APNG и MNG, но с анимацией в этих форматах также туго, как с AVI.

Поискав нативные компоненты для отображения gif-анимации в Delphi (то есть не просто поддержка формата, а именно вычленение свойств анимации и ее отображение), можно сказать, что выбор весьма невелик. Это TGifImage от Anders Melander (который стал настолько популярен, что уже входит в поставку с делфи (начиная, кажется, с 2007. в 2009 точно есть)) и TjvGIFImage из известного пакета компонент JEDI. В целом компоненты справляются со своей задачей. Они умеют извлекать, отображать и корректно сохранять информацию из gif-анимаций. И если нужно отобразить небольшое число анимаций, то на этом прочтение статьи можно закончить:) Проблемы начинаются, когда нужно отображать достаточно большое число анимированных объектов или часто извлекать отдельные кадры для последующей обработки. Оба компонента страдают большим недостатком — обе реализации потребляют непомерное число GDI ресурсов и, при интенсивном использовании, дают ощутимые утечки и со временем они могут стать причиной падения вашей программы с ошибкой EOutOfResources.

Используя TGifImage в Qip Infium мы столкнулись с проблемой прожорливого потребления и утечки GDI ресурсов — ведь смайлы у нас в формате gif и используются они весьма интенсивно. Сначала было введено ограничение в 20 смайлов на закладку и ряд ухищрений, чтобы потребление GDI было меньше, однако проблему утечки это не решало. И в конце концов, я решил поискать альтернативные решения. Это должна была быть библиотека, не использующая лишних dll (дабы можно было контролировать весь процесс работы, ловить баги внутри dll — не самая лучшая перспектива) и не страдающая описанным выше недугом.

В процессе поиска я наткнулся на замечательнейшую библиотеку — Vampire Imaging Library. Это кроссплатформенная библиотека на языке Object Pascal, поддерживающая большое число форматов и обладающая поистине широкими возможностями. Настолько стройной, продуманной архитектуры в библиотеках я практически не видел. Одним словом, я влюбился в нее с первого взгляда:) И, хотя библиотека позиционируется скорее для игровых разработчиков, для VCL она тоже вполне пригодна. И поддержка GIF формата заявлена. Так что выбор пал на нее. Однако, как оказалось тогда, поддержка gif была весьма далека от тех требований, что я ставил изначально. Потребление GDI было нулевым, однако не было полной поддержки GIF, не было возможности извлечения информации о кадрах и ни о какой полноценной интеграции в VCL не было и речи. Но библиотека настолько хороша и продумана, что грех было отказываться от такой красоты. Поэтому я решил внести свою лепту в библиотеку и довести поддержку GIF (а заодно и интеграцию с VCL) до ума.

Результат долгой работы вы можете наблюдать здесь, скачав последний релиз (также можно скачать последний срез исходников из svn). Я постарался сделать переход к этой библиотеке от TGifImage максимально простым. Теперь достаточно подключить модуль ImagingComponents1 в uses и вы можете загружать в TImage любую gif анимацию и наслаждаться ею в рантайме2 :) Перечислю преимущества и недостатки моей реализации.

Преимущества:

  1. Отстутствует потребление GDI, поскольку хранение не в TBitmap, а в массиве цветов/палитре (можно использовать как DIB секцию). GDI потребляются только при отрисовке и сразу же освобождаются.
  2. Гораздо более низкое потребление памяти при загрузке нескольких экземпляров одного и того же gif за счет собственного механизма подсчета ссылок.
  3. Честно украденный из TjvGifImage и слегка переработанный алгоритм вкупе с рядом ухищрений по буфферизации отрисовки показывает также более низкое потребление процессора.
  4. Более корректное отображение анимации. К примеру, полностью поддерживается TrueColor gif (не показатель, конечно, но тем не менее).
  5. Анимация работает также в формах внутри dll.
  6. Имеется возможность масштабирования как отдельных фреймов, так и всей анимации в целом.

Недостатки:

  1. Поскольку TImage не особо предназначен для анимации, то приходится мириться с возникновением артефактов при отрисовке. Когда они могут возникнуть можете прочитать в комментариях к методу Draw. К сожалению, я не смог найти нормального способа, чтобы избавиться от них самой библиотекой. Однако, есть несколько способов от нее избавиться, вручную задав цвет фона или подложку в виде битмапа (см. свойства BackgroundColor, BackgroundBitmap и BackgroundSharing). Моих знаний не хватило, чтобы подобрать такие условия, чтобы обновление бекграунда проходило корректно. Может, вам удастся?
  2. При сохранении измененного gif могут потеряться заголовки, которые библиотека игнорирует — комментарии, Application Extension, отличный от NETSCAPE 2.0; а также может иметь больший размер на диске, потому что библиотека при работе с форматом GIF оперирует только 8-битным представлением цвета. Опять таки, это можно исправить, сохраняя не через библиотеку, а через TFileStream к примеру.
  3. Нет работы с ClipboardFormat. Мне это было как-то ненужно, а лентяй я страшный. :о)
  4. Возможны баги и глюки, поскольку используется довольно много полушаманских способов, дабы достичь самоанимации в TImage. Плюс достаточно много кода работает с указателями и сам автор говорит, что библиотека пока не thread-safe (но для отображения gif анимации это и не нужно при аккуратном использовании). Я проводил тестирование на 20 000 самых разнообразных gif анимаций, но вполне могу появиться такие страшные гифки, не отвечающие стандартам, от которых библиотека может загнуться (если вы такую встретите — просьба сообщить здесь).

Должен предостеречь вас. Если у вас нет тяжелого наследия в виде горы кода, закладывающегося на особенности VCL, то использовать самоанимацию в TImage я бы крайне не советовал. Вместо этого лучше сделать свой контрол и, слегка поправив в классе TImagingGraphic, реализовать отрисовку самому. Подскажу как: достаточно в общем-то по умолчанию присваивать свойству SelfAnimated значение False (но тогда расчет интервалов надо будет делать самому), либо переделать реакцию на смену кадра в PaintTriggered. В папке с модулем вы найдете модуль RVVampireGifAnimate, позволяющий работать с гиф анимацией в TRichView – пример того, как можно работать с классом самому (в TRichView расчет интервалов свой).

Кроме того, проникнув духом библиотеки, базовый класс написан «на вырост» — для реализации форматов MNG и APNG. Поддержка MNG в библиотеке уже есть, APNG планируется. И может быть даже кто-то заинтересуется этими форматами и сделает наконец бесплатный полнофункциональный редактор для создания анимаций в формате APNG и/или MNG :о).

Прошу не забрасывать меня помидорами, а на все огрехи показывать и тыкать меня носом в мануалы:) Исправление ошибок/расширение функционала только приветствуется. Мы эту библиотеку уже используем достаточно широко, чего и вам советую;)

Естественно, текущая реализация не финальная. Следите за изменениями библиотеки, и, конечно же, любая помощь проекту только приветствуется ;)

В прилагаемом архиве вы найдете 3 демо-проекта, демонстрирующих преимущества моей реализации (при запуске TImageSample(TGIFImage).exe будьте готовы к вылету программы с кучей ошибок. Просто поверьте на слово, что TGIFImage не справится с отображением такого количества анимаций:))

P.S. Хотел выложить статью к юбилею королевства, но релиз библиотеки несколько затянулся. Всех с наступающим новым годом!

1Замечу, что подключать нужно модуль из папки Extras\Contrib\ExtraGIF\

2Если загрузка идет через TGraphic и только потом загружается в TImage, то пользуйтесь классом TImagingGifGraphic или его символическим близнецом TGifImage (добавлен для более безболезненного перехода от TGifImage, если он уже используется в проекте и не используются какие-то специфические свойства)

К статье прилагаются примеры




Смотрите также материалы по темам:
[GDI, рисование на канве] [Анимация] [Растры, BMP]

 Обсуждение материала [ 14-11-2011 07:11 ] 10 сообщений
  
Время на сайте: GMT минус 5 часов

Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
Функция может не работать в некоторых версиях броузеров.

Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

 
© При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
Все используемые на сайте торговые марки являются собственностью их производителей.

Яндекс цитирования