![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Помогите с реализацией алгоритма [D7, XP]
Gens © (2006-09-03 15:20:00)Здравствуйте уважаемые,надеюсь вы мне поможите с моими затруднениями возникшими в процессе разработки.Я использую Kol+MCK, но это не суть важно.И так:
Файл грубо говоря выглядит следующим образом
В начале заголовок:
GRPHeader: record
Sprites: LongInt; //Количество спрайтов
FullWidth: LongInt; //Полная ширина изображения
FullHeight: LongInt; //Полная высота изображения
End;
По адресу $06 располагается SAT (Sprite Allocation Table) - таблица расположе-
ния спрайтов. Каждая запись имеет следующую структуру:
SATRecord: record
OffsetLeft: Byte; //Смещение спрайта от левого края изображения
OffsetTop: Byte; //Смещение спрайта от верхнего края изображения
SpriteWidth: Byte; //Ширина спрайта
SpriteHeight: Byte; //Высота спрайта
Offset: LongInt; //Смещение до данных спрайта
End;
Считываю данные следующим образом:
var
GprStream,NewStream: PStream;//Потоки для открытия и конвертирования спрайтов
Sprites: LongInt; //Количество спрайтов
FullWidth: LongInt; //Полная ширина изображения
FullHeight: LongInt; //Полная высота изображения
OffsetLeft: Byte; //Смещение спрайта от левого края изображения
OffsetTop: Byte; //Смещение спрайта от верхнего края изображения
SpriteWidth: Byte; //Ширина спрайта
SpriteHeight: Byte; //Высота спрайта
Offset: LongInt; //Смещение до данных спрайта
BMPHeader: RECORD //Заголовок *.bmp формата(необходим для конвертирования)
FullSize: LongInt;
_H1: LongInt;
_C1: LongInt;
_C2: LongInt;
X: LongInt;
Y: LongInt;
_C3: Word;
_C4: Word;
_H2: LongInt;
_H3: LongInt;
DataSize1: LongInt; //DataSize=X*Y+2*Y
DataSize2: LongInt; //DataSize=X*Y+2*Y
_C5: ARRAY[1..8]OF Byte;
END;
inplemenation
Procedure OpenGpr(FileName: string;ProgressBar:PControl);
var
Binfo: longInt;
begin
GprStream:=NewReadFileStream(FileName);
ProgressBar.Position:=0;
ProgressBar.MaxProgress:=GprStream.Size;
ProgressBar.Position:=GprStream.Position;
GprStream.Seek(Binfo,spBegin);
While GprStream.Position < $06 do //Пока позиция не равна позиции SAT читаем Header
begin
GprStream.Read(Sprites,4);
GprStream.Read(FullWidth,4);
GprStream.Read(FullHeight,4);
end;
if GprStream.Position = $06 then
repeat
begin
GprStream.Read(OffsetLeft,1);
GprStream.Read(OffsetTop,1);
GprStream.Read(SpriteWidth,1);
GprStream.Read(SpriteHeight,1);
GprStream.Read(Offset,4);
{***расшифровка спрайта***}
until
end;
Собственно трудности с реализацией расшифровки спрайта - алгоритм выглядит следующим образом:
В заголовке спрайта последовательно
размещены смещения на каждую из строк спрайта. Наша задача состоит в том, чтобы
последовательно перейти на начало каждой строки и по определенной схеме эту
строку расшифровать . Да, да , именно расшифровать, потому что этот формат ока-
зался не таким уж простым. Во всяком случае - на первый взгляд . Итак, будем
считать, что мы перешли к некой строке. Строка состоит из нескольких сегментов.
Каждый сегмент состоит из байта-описателя и, собственно, байтов данных. Левые 2
бита байта-описателя определяют тип сегмента (в дальнейшем - Type), остальные 6
бит - длина сегмента (в дальнейшем - Length). Вот возможные типы сегментов и их
значения:
*** Таблица типов сегментов ***************************************************
b00 - Сегмент представляет собой последовательность пикселей. Группа пикселей
длиной в Length считывается сразу за байтом - описателем.
b01 - Сегмент представляет собой последовательность одинаковых пикселей длиной
в Length. Образец пикселя считывается сразу за байтом-описателем.
b10 - Сегмент представляет собой последовательность прозрачных пикселей длиной
в Length.
b11 - Сегмент представляет собой последовательность прозрачных пикселей длиной
в Length+64.
*******************************************************************************
Рассмотрим конкретный пример строки.
*** Образец строки ****************************
86 09 47 8F 8F 44 46 8D 42 8E 49 44 94 01 49 9E
***********************************************
1. Позиция в строке - $00: байт-описатель первого сегмента - $86. Разбиваем
его на левую (2 бита) часть и правую (6 бит). Левая равняется b10 - это тип
сегмента. Правая - b000110, или d6 - это длина сегмента. Значит, тип равен
b10. Следовательно сегмент этот определяет прозрачную строку длиной в 6 пик-
селей. Раз пиксель прозрачный, значит его значение нам считывать не нужно -
оно всегда равняется $00. Получаем первые 6 пикселей строки.
2. Позиция в строке - $01: байт-описатель второго сегмента - $09. Type=b00,
Length=d9. Тип b00 подразумевает чтение группы байтов длиной в 9 и формиро-
вания из них строки.
3. Позиция в строке - $0B: байт-описатель третьего сегмента - $44. Type=b01,
Length=d4. Раз тип равен b01 , значит строка длиной в 4 пикселя состоит из
одинавовых пикселей, образец которого помещается в следующем байте.
4. Позиция в строке - $0D: байт-описатель четвертого сегмента - $01.Type=b00
, Length=d1. Читаем следующий байт. Это и будет короткий сегмент.
4. Позиция в строке - $0F: байт-описатель пятого сегмента - $9E.Type=b10,
Length=d30. Это - прозрачный сегмент длиной в 30 пикселов.
Таким образом, в сумме все эти сегменты образуют полную строку длиной в 50 пик-
селов (6+9+4+1+30). Таким же образом разбираются и остальные строки.
Так вот.......Как это реализовать???Заранее благодарен.
Zeqfreed (2006-09-03 16:24:00) [1]> [7] Gens © (03.09.06 16:20)
http://www.delphimaster.ru/cgi-bin/forum.pl?id=1157121160&n=18
Gens (2006-09-03 16:20:00) [2]Можно пример разбиения байта на биты?
Desdechado (2006-09-03 15:53:00) [3]> GRPHeader: record
> Sprites: LongInt; //Количество спрайтов
> FullWidth: LongInt; //Полная ширина изображения
> FullHeight: LongInt; //Полная высота изображения
> End;
> По адресу $06 располагается SAT
Вообще-то longint - 4 байта. Поэтому record имеет длину 12, а не 6.
Да и то,только в случае packed record. Для спрайтов это тоже актуально.
Zeqfreed (2006-09-03 15:50:00) [4]> [4] Gens © (03.09.06 15:48)
Посредством логических операторов and, or и др.
Gens (2006-09-03 15:48:00) [5]А трудности вот в чём...Как байт разбить на биты и произвести необходимые вычисления?
Gens (2006-09-03 15:42:00) [6]Для открытия и конвертирования графики из старкрафта=)И для собственного обучения=)
Zeqfreed (2006-09-03 15:40:00) [7]В чем конкретно трудности? А то такое ощущение, что опять требуют готового кода.
SerJaNT (2006-09-03 15:23:00) [8]Нихрена себе, и это в разделе для начинающих... Если не секрет, для чего это?