TIM2
Материал из GTAModding.ru
TIM2 - растровый графичесий формат приставки Sony Playstation 2. C небольшими изменениями1 используется в PS2 *.txd
-файлах трилогии GTA и в других играх.
Содержание |
Структура файла
В начале файла содержится заголовок размером 16 байт, имеющий следующую структуру:
struct tim2_header { BYTE sign[4]; WORD format_id; WORD pictures; BYTE padding[8]; }
-
sign
- 4 байта - всегда равно "TIM2" -
format_id
- 2 байта - равно 4 (??) -
pictures
- 2 байта - количество изображений в файле. -
padding
- 8 байт - зарезервированное место (байты могут быть нулями)
Далее идёт заголовок изображения, повторяющийся N раз (N=picures
) вместе с палитрой и самим растром.
struct tim2_imge_header { DWORD total_size; DWORD clut_size; DWORD image_size; WORD header_size; WORD clut_colors; BYTE pict_format; BYTE mipmaps; BYTE clut_type; BYTE image_type; WORD image_width; WORD image_height; BYTE unknown[24]; };
-
total_size
- 4 байта - общий размер (размер изображения, палитры и заголовка) -
clut_size
- 4 байта - размер палитры (равен количеству цветов, умноженному на 4) -
image_size
- 4 байта - размер изображения (размер растра, равен произведению длины, ширины и размеру пикселя в байтах) -
header_size
- 2 байта - размер заголовка (этой структуры). Важно отметить, что размер этой структуры колеблется в довольно больших пределах (поле unknown может больший или меньший размер). Возможно, при программировании, есть смысл не включать unknown в структуру, а считать его основываясь на значении поляheader_size
. -
clut_colors
- 2 байта - количество цветов в палитре -
pict_format
- 1 байт - неизвестно, обычно равно 0 (нулю). -
mipmaps
- 1 байт - количество мипмапов. -
clut_type
- 1 байт - неизвестно, обычно равно 3 -
image_type
- 1 байт - тип изображения:
0 - NONE 1 - RGB16 2 - RGB24 3 - RGB32 4 - IDTEX4 - для 4-битных текстур 5 - IDTEX8 - для 8-битных текстур
-
image_width
- 2 байта - ширина изображения в пикселях -
image_height
- 2 байта - высота изображения в пикселях
Далее идут данные растра, за ними - данные палитры.
Структура палитры
(Палитра идёт после растра, но вначале нужно объяснить структуру палитры)
Если значение BPP равно 4 и 8 битам на пиксель, то используется палитра, хранящая в себе все эти цвета. Количество цветов, как ясно из школьной программы или дискретной математики равно bpp2
, т.е. 16 для 4 бит и 256 для 8ми. Каждый цвет, в любом случае, представляет собой 4 байта в формате RGBA - Red (красный), Green(зелёный), Blue (синий), A(альфа).
Сответсвенно, размр паритры равен colors·4
байт. Форматы, использующие менее 16 цветов не испоьзуются, а более 256 не имеют палитры вообще.
Структура растра
Растр сделан наподобие довольно известного формата BMP (Windows Bitmap).
- Если текстура имеет глубину цвета 8бит, то растр представляет собой массив размером
width x height
типа BYTE, каждый байт которого содержит номер (индекс) цвета в палитре. НО для 8-битных текстур есть одина особенность - если разбить палитру на блоки по 32 цвета, то вторая и третья 8-ки цветов как бы поменяны местами (такое преобразование может понадобиться при создании BMP из TIM2):
| 0 1 2 3 | 4 5 6 7 | --> | 0 2 1 3 | 4 6 5 7 | (каждая цифра - блок из 8 цветов)
- Если текстура 4-битная, то растр представляет собой массив размером
width x height / 2
типа BYTE, в котором каждый байт задаёт два цвета, наподобие того, как в 8-битных цвет задаёт один байт. Палитра никаких особенностей не содержит. - Если текстура содержит 32 бита на пиксель, то она представляет собой массив цветов такой же струкуры, как и цвет палитры, т.е.
width x height x 4
. Точно также в формате RGBA. - Если текстура 16-битная, то растр хранится согласно полю в одном из форматов RGB (5-5-5, 5-6-5) или ARGB(1-5-5-5) или RGBA(4-4-4-4). В GTA обычно используется 1555.
Swizzling
В TXD-архивах GTA используется технология swizzling'а, которая, в общих чертах, позволяет выиграть в производительности игры за счёт нестандартного расположения пикселей. По своей сути swizzling - операция на блоке изображения размером 16x8. Если изображение меньше чем 16 по ширине, то ширина всё равно будет 16 (в сучае с 4-битными текстурами, это условие работает для 32 пикселей в ширину - по видимому, дело ещё и в размере строки в байтах). При этом swizzling применяется к большому изображению, а результат "обрезается" до нужных размеров. В зависимости от количества битов на пиксель (bpp) алгоритм подвергается некоторым вариациям (из-за способа хранения одного пикселя). Следует также отметить, что в GTA3 некоторые текстуры (4 и 8 бит) хранятся без swizzling'а.
Код unswizzling'а для 8-битных PS2 текстур выглядит так:
void unswizzle8( char* buf, int width, int height ) { char* swizzled = new char[width*height]; memcpy(swizzled, buf, width*height); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int block_location = (y & (~0xf)) * width + (x & (~0xf)) * 2; int swap_selector = (((y + 2) >> 2) & 0x1) * 4; int posY = (((y & (~3)) >> 1) + (y & 1)) & 0x7; int column_location = posY * width * 2 + ((x + swap_selector) & 0x7) * 4; int byte_num = ((y >> 1) & 1) + ((x >> 2) & 2); // 0,1,2,3 buf[(y * width) + x] = swizzled[block_location + column_location + byte_num]; } } delete [] swizzled; }
Преобразование в BMP
Логичный вопрос - преобразование одного растрового формата в другой (без потери качества). Итак,
- Палитру (для 4bpp и 8bpp) или же сам растр нужно преобразовать из RGBA в BGRA.
- Растр нужно отразить построчно сверху вниз.
- В 4-битных текстурах нужно поменять местами старшие и младшие 4 бита каждого байта растра.
- Далее собрать обший заголовок или воспользоваться готовыми функцияи Windows. (Информация по формату BMP есть здесь)
Обратите внимание, что
- 8- и 4-битные BMP не поддерживают альфа-канал (маску).
- Маску поддерживают 32-битные BMP, поэтому для отображения текстуры вместе с альфой именно в BMP можно воспользоваться им.
Примечания
^В TXD-файлах текстуры хранятся в с использованием swizzling'а. Исключение составляют только некоторые 4-битные текстуры.