GIF (англ. Graphics Interchange Format — формат для обмена изображениями; произносится /dʒɪf/, но многие произносят /gɪf/ или «гиф»[1]) — формат хранения графических изображений. Формат GIF способен хранить сжатые без потерь изображения в формате до 256 цветов Независящий от аппаратного обеспечения формат GIF был разработан в 1987 году (GIF87a) фирмой CompuServe для передачи растровых изображений по сетям. В 1989-м формат был модифицирован (GIF89a), были добавлены поддержка прозрачности и анимации. GIF использует LZW-компрессию, что позволяет неплохо сжимать файлы, в которых много однородных заливок (логотипы, надписи, схемы).
Структура GIF
Файл состоит из 13 байт заголовка и дополнительных блоков. Перед каждым блоком дополнительной информации идет идентификатор. Существует три типа идентификаторов:
1. 000h-07Fh (0-127) - блоки отображения графики, за исключением конца файла (3Bh) 2. 080h-0F9h (128-249) - блоки управления 3. 0FAh-0FFh (250-255) - специальные блоки
К каждому блоку могут быть прикреплены дополнительные данные в виде последовательности под блоков:
размер данных | 1 | данные | -//- | Такая последовательность завершается под блоком нулевой длины.
Заголовок:
Подпись | 3 | Содержит строку "GIF".
| Версия | 3 | Содержит последние две цифры года (начиная с 1987 и заканчивая 2086 ) и букву в нижнем регистре (от a до z).
| Ширина | 2 | Логическая ширина экрана в пикселях.
| Высота | 2 | Логическая высота экрана в пикселях.
| биты 0-2 - глубина цвета | 3/8 | Предназначено для определения размера палитры по формуле <размер>=(1 shl (<глубина цвета>+1))*3.
| бит 3 - сортировка | 1/8 | Если этот бит
установлен, то цвета в палитре рассортированы от наиболее значимого к
наименее значимому. Это помогает при выводе изображения на устройство,
не поддерживающее его глубину цвета.
| биты 4-6 - глубина цветового разрешения | 3/8 | Содержит количество бит на пиксель минус 1.
| бит 7 - палитра | 1/8 | Если этот бит установлен, то поле "Палитра" присутствует.
| Цвет фона | 1 | Индекс цвета для заполнения прозрачных участков изображения
| Отношение ширины к высоте | 1 | Используется
для расчёта отношения ширины к высоте (aspect ratio) по формуле Aspect
Ratio = (Pixel Aspect Ratio + 15)/64. Таким образом обеспечивается
одинаковое отображение при различных разрешениях экрана.
| Палитра | ? | Содержит таблицу цветов в формате RGB 24 бита |
Приложение:
Идентификатор блока | 1
| Содержит восклицательный знак - 21h.
| Тип расширения | 1
| Содержит 0FFh.
| Размер блока | 1
| Содержит размер блока от следующего поля до начала данных (11 байт) | Идентификатор приложения | 8
| Имя приложения для обработки данных в ASCII кодировке.
| Код идентификации | 3
| Уникальный идентификатор приложения |
К этому блоку присоединяются данные которые обрабатываются соответствующим приложением. Это может быть скрипт для обработки браузером. Пример: Идентификатор приложения - NETSCAPE Код идентификации - 2.0 Размер данных - 3 0 байт данных - 1 1-2 байты данных - количество итераций повторения анимации (0 - бесконечное повторение)
Блок управления:
Идентификатор блока | 1
| Содержит восклицательный знак - 21h.
| Тип расширения | 1
| Содержит 0F9h
| Размер блока | 1
| Содержит размер блока от следующего поля до символа завершения (4 байта) | бит 0 - прозрачность | 1/8 | Если этот бит установлен, то поле индекса прозрачности имеет смысл | бит 1 - ожидание ввода | 1/8 | Если этот бит установлен, то приложение должно загружать следующий кадр
при обнаружении активности пользователя. Однако это не отменяет время
задержки
| биты 2-4 - Метод перехода | 3/8 | Определяет действия при смене кадра.
0 - Ничего не делать (в действительности нужно оставить картинку на экране) 1 - Оставить картинку на экране 2 - Закрасить экран фоновым цветом 3 - Восстановить содержимое экрана
| биты 5-7 - х.з. | 3/8 | х.з
| Время задержки | 2 | Содержит время в сотых долях секунды и определяет задержку между кадрами.
| Индекс прозрачности | 1 | Содержит индекс цвета, который определён как прозрачный
| К этому блоку может быть присоединена дополнительная информация.
Дескриптор изображения:
Идентификатор блока | 1 | Содержит запятую - 2Ch
| X-координата | 2 | Позиция левого края изображения относительно левой границы экрана в пикселях | Y-координата | 2 | Позиция верхнего края изображения относительно верхней границы экрана в пикселях | Ширина | 2 | Ширина растра в пикселях | Высота | 2 | Высота растра в пикселях
| биты 0-2 - локальная глубина цвета | 3/8 | Предназначено для определения размера локальной палитры по формуле <размер>=(1 shl (<локальная глубина цвета>+1))*3 | биты 3-4 - зарезервировано | 2/8 | -//-
| бит 5 - сортировка | 1/8 | Если этот бит установлен, то цвета в локальной палитре рассортированы
от наиболее значимого к наименее значимому. Это помогает при выводе
изображения на устройство, не поддерживающее его глубину цвета | бит 6 - чересстрочное изображение | 1/8 | Если этот бит установлен, то растр сохранён в чересстрочном порядке:
Каждая 8 строка начиная с 0 строки
Каждая 8 строка начиная с 4 строки
Каждая 4 строка начиная со 2 строки
Каждая 2 строка начиная с 1 строки
| бит 7 - локальная палитра | 1/8 | Если этот бит установлен, то локальная палитра присутствует | Локальная палитра | ? | Содержит таблицу цветов в формате RGB 24 бита | Размер корня LZW | 1 | Содержит начальный размер кода архива минус 1 | К этому блоку присоединяется поток LZW-данных.
Комментарий:
Идентификатор блока | 1
| Содержит восклицательный знак - 21h | Идентификатор блока | 1
| Содержит 0FEh |
К этому блоку присоединяется текст в 7-битной ASCII кодировке (по 8 бит на символ, но значение имеют лишь первые 7).
Текст:
Идентификатор блока | 1 | Содержит восклицательный знак - 21h | Тип расширения | 1 | Содержит 1
| Размер блока | 1 | Содержит размер блока от следующего поля до начала данных (12 байт) | X-координата | 2 | Положение левого края текстовой строки относительно левой границы экрана в пикселях | Y-координата | 2 | Положение верхнего края текстовой строки относительно верхней границы экрана в пикселях | Ширина | 2 | Ширина текстовой строки в пикселях | Высота | 2 | Высота текстовой строки в пикселях | Ширина символа | 1 | Ширина символа в пикселях | Высота символа | 1 | Высота символа в пикселях | Цвет текста | 1 | Индекс цвета в глобальной палитре для текста | Цвет фона | 1 | Индекс цвета в глобальной палитре для фона |
К этому блоку присоединяется текст в 7-битной ASCII кодировке (по 8 бит
на символ, но значение имеют лишь первые 7). Если символ не попадает в
диапазон 20h-0F7h, то он должен быть заменён пробелом (20h)
Отображение Самое сложное при загрузке GIF`а правильно отобразить его на экране. Вот общий алгоритм отображения:- Закрасить экран цветом фона.
- Загрузить кадр.
- Вывести кадр на экран в соответствии с данными, взятыми из
блока управления (ширина, высота, координаты X и Y) учитывая
прозрачность.
- Сделать задержку в соответствии с полем "время задержки" в блоке управления.
- Обработать изображение в соответствии с полем "метод перехода" в блоке управления.
- Если ещё остались кадры, то переход к пункту 2.
Алгоритм распаковки LZW с переменным размером:
- Объединяем под блоки LZW-данных в единый поток
- Устанавливаем исходный размер
- Считываем код
- Если код - CC,то переходим к шагу 2
- Если код - EOI, то заканчиваем обработку
- Если код < CC то записываем его в выходной поток
- Иначе вычитаем из кода (CC+2) и записываем в выходной поток соответствующую строку из словаря
- Добавляем в словарь указатель на только, что записаную строку
в выходном потоке (при этом если записан только один символ - длина
строки = 2)
- Если индекс текущего элемента словаря превышает пороговое число, то увеличиваем размер кода
- Переходим к шагу 3
СС = 1 shl (<исходный размер>-1)
EOI = CC+1
Пороговые числа высчитываются по формуле
Xi=(Xi-1+2)*2+X0
в которой X0=CC-2, а i изменяется от 1 до 12. Причём сразу после 1022 должно идти 4094. Чтобы понять это смотрите исходник.
В качестве словаря удобно использовать массив структур
length | rd 1 | ;длина строки
| pstr | rd 1 | ;указатель на строку | Пример Исходник оперирует процедурой LoadGIF. Она оформлена в виде include-файла к FASM. Её прототип таков:LoadGIF(
LPSTR | filename | //имя файла в кодировке ANSI
| PVOID | raster | //указатель на массив указателей на растр формата RGBA 32
| VOID | info | //указатель на структуру с дополнительной информацией
| ); |
Структура info содержит следующие поля
ULONG | width | //ширина кадра в пикселях
| ULONG | height | //высота кадра в пикселях
| ULONG | frames | //количество кадров |
Код процедуры берёт на себя всю работу по отображению и выдаёт массив отформатированых кадров формата RGBA 32 бит на пиксель.
Программа понимает чересстрочные и анимированные изображения, а также
изображения без палитры. Интерфейс прост - закиньте (Drag&Drop)
файл в окно и всё готово. В процессе тестирования я обнаружил файл (он
присутствует в архиве), который вызывает сбой в работе. Причина сбоя
неясна и это единственный обнаруженый случай. Для компиляции примера
необходим файл Windows.inc
Список источников - Graphics Interchange Format Programming Reference (31 July 1990)
- А.С.Самотохин Описание формата GIF (Москва, ноябрь 1990 г.)
- Arturo San Emeterio Campos Lzw, gif decoding (Barcelona 23-07-1999)
- Royal E. Frazier Jr. All About GIF89a (March 1997)
|