----------------------------- Формат ani-файлов на спеке -------------- - - - +00 "GIF animation" : сигнатура +13 =0 +14 размер по X в знакоместах (1-32) +15 размер по Y в пикселях (1-192) +16... данные анимации (кадры) анимация представляет собой последовательность кадров для каждого кадра в начале следуют два байта: +0 длительность кадра в 1/50 сек +1 тип упаковки кадра если длительность=255 или тип упаковки нераспознан плейером, то мультик возвращается на самый первый кадр. и конвертер, и бета редактора выбирают наилучший метод упаковки из 9 имеющихся (по методу сжатия изображения) ---- тип 0 это неупакованый спрайт в линейном формате. Бывает, что кадр ни в какую ни одним другим методом не жмется. При наличии цвета строка атрибутов идёт после каждых 8 строк изображения ---- тип 1 взят из статьи "Сжатие графической информации и что из этого можно получить" (C) Vitamin/CAIG/2001. Кадр разбивается на знакоместа (размер по Y увеличивается до ближайшего кратного 8 числа). Рассмотрим упаковку такого знакоместа: #55,#ff,#55,#ff,#ff,#ff,#50,#05 начиня со второго байта делаем XOR'инг с предыдущим: #55,#aa,#aa,#aa,#00,#00,#af,#55 создадим флаговый байт - отметим 0 байты, которые равны предыдущему, 1 - неравны. для 1го байта предыдущим считается 0. Только биты в обратном порядке - правый бит отвечает за первый байт. Получим: 1,1,0,1,0,0,1,1 = #D3 теперь выводим в поток сначала флаговый байт, а потом - те байты XOR'инга, для которых установлен бит в флаговом байте: #D3,#55,#AA,#00,#AF,#55 в итоге вместо 8 байт знакоместа получили 6 байт в упакованом формате. распаковка идет по следующему алгоритму: byte=0 xorbyte=0 flag=байт флагов цикл 8 RR flag if carry=1 then берем из потока новый xorbyte byte=byte xor xorbyte вывод byte на экран кц Количество упакованых блоков, естественно, равно числу знакомест в кадре. Знакоместа пакуются слева направо сверху вниз (т.е сначала ряд верхних, потом следующий ряд, и так до низа) ---- тип 2 очень похож на тип 1, но в байте флагов сброшены те биты, соответствующие нулям в XOR'инге. Т.е для примера из типа 1 флаги будут: 1,1,0,0,1,1,1,1 = #CF и в поток выдастся #CF,#55,#aa,#aa,#aa,#af,#55 тут получилось что выигрыш минимален, но это не значит что он хуже типа 1 здесь распаковка такая: byte=0 flag=байт флагов цикл 8 RR flag if carry=1 then byte=byte xor (байт из потока) вывод byte на экран кц ---- тип 3 это тот же тип 1, но полученое знакоместо не выводится прямиком на экран, а накладывается по XOR на соответствующее знакоместо предыдущего кадра. ---- тип 4 аналогично: кадр упакован типом 2 и по XOR накладывается на предыдущий. Если кадр меняется не сильно, то в результате его XORинга с предыдущим кадром получается много пустых знакомест, которые пакуются лучше всего, и в этом случае тип 3 и тип 4 на голову выше остальных типов упаковки. Теперь о новых типах: ---- типы 5-9 это спрессованые типы 1-4. Вводится такое понятие как флаг 2го уровня. биты этого флага определяют состояние байтов флагов для 8 следующих за ним знакомест. Если бит=0, то флаг=0 (в этом случае в поток пишется только цвет, да и то если он есть), а если=1, то флаг не нулевой, и блок идёт в поток по полной программе (флаг,данные и может цвет) На примере: допустим, упакованый кадр (для широты кругозора будет с неупакованым цветом) начинается так... DB %10010000 DB 1 DB 2 DB 3 DB 4 DB %00100001,#FF,#55,5 DB 6 DB 7 DB %10000000,#77,1 Первый байт - флаг 2го уровня. Смотрим за состоянием битов начиная с нулевого (правого) 0 - блок пустой (типы 5,6) или не меняется (типы 7,8) из данных блока в потоке только цвет (1) 0 - то же (цвет 2) 0 - то же (цвет 3) 0 - то же (цвет 4) 1 - АГА! блок в поток выложен полностью берем флаг блока (%00100001) и соответственно типу распаковываем блок. цвет 5 0 - блок пустой. цвет 6 0 - блок пустой. цвет 7 1 - полный блок. (флаг %10000000, данные #77, цвет 1) Всё, разобрались с 8 блоками... Дальше следует то же самое - флаг 2го уровня и всё что к нему прилагается Конечно, общее число блоков в кадре, не обязательно кратно 8. В таких случаях ненужные биты последнего флага 2го уровня не учитываются. Что мы с этого получаем? Каждый нулевой байт флагов стягивается в 1 бит флага 2го уровня, но при этом каждый ненулевой распухает до 9 бит. Например, полностью пустой кадр без цвета ужмется в страшные 64 раза (во-первых пустые знакоместа жмутся в нулевой флаговый байт, а во вторых каждый нулевой флаговый байт жмется в 1 бит флага 2го уровня) ---- теперь про цвет Под информацию о наличии цвета и его упаковке (да, и это тоже есть!) передают старшие биты типа кадра. b7 = 0 если цветового потока нет (т.е он полностью идентичен потоку предыдущего кадра) = 1 если он есть b6 = 0 если цвет не кодируется (т.е за каждым упакованым знакоместом идёт 1 байт цвета) = 1 если кодируется (пропускаются знакоместа с неизменяющимся цветом) а теперь я сказать по бумажка... при упаковке цвета введен еще и контрольный байт для цвета. весьма и очень похож на флаг 2го уровня - если в нем бит = 0, то цвет знакоместа не поменялся по отношению к предыдущему кадру и в потоке отсутствует. А если бит = 1, то вслед за знакоместом идет его цвет. Как и флаг 2го уровня, флаг цвета встречается каждые 8 знакомест. Если оба эти флага наличиствуют (напр, тип 5 с упакованым цветом: #С5), то первым всегда идет флаг 2го уровня, а за ним - флаг цвета. Полная схема потока кадра вроде как выглядит так: [длительность] [тип] b0..5-тип упакрвки b6-цвет спрессован b7-цвет присутствует [флаг 2 уровня] только для типов 5-9 (определяет наличие пар [флаг][блок]) [флаг цвета] только для спрессованого цвета (определяет наличие компонента [цвет]) [флаг 1][блок 1][цвет 1] [флаг 2][блок 2][цвет 2] [флаг 3][блок 3][цвет 3] [флаг 4][блок 4][цвет 4] [флаг 5][блок 5][цвет 5] [флаг 6][блок 6][цвет 6] [флаг 7][блок 7][цвет 7] [флаг 8][блок 8][цвет 8] [флаг 2 уровня] ... Ну и как всегда приоритет в выборе типа упаковки (и изображения, и цвета) - размер...