IPB

Добро пожаловать, гость ( Вход | Регистрация )

> Работа с палитрой на примерах
Siberian GRemlin
Jun 16 2007, 04:51
Сообщение #1


Advanced Member
***

Группа: CTPAX-X
Сообщений: 538
Регистрация: 4-February 08
Пользователь №: 2
Спасибо сказали: 223 раз(а)



Уважаемые, объясните что к чему. Вроде, всё правильно делаю, а изображение похоже с косяками.
http://slil.ru/24516685 - исходник + примеры из игры Earth 2140
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
 
Reply to this topicStart new topic
Ответов(1 - 3)
-=CHE@TER=-
Jun 16 2007, 22:13
Сообщение #2


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,460
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 332 раз(а)



Siberian GRemlin!
Ночью нужно спать. (*улыбается*)

Подсказываю, где ошибка:
QUOTE
Pallete: array[1..256] of record
R, G, B: byte;
end;

...

TempStream.ReadBuffer(b,1);
Image1.Canvas.Pixels[(j-1),(i-1)]:=((Pallete[b].R*$10000)+(Pallete[b].G*$100)+(Pallete[b].B));}

Байт-то у тебя от 0 до 255, а не от 1 до 256!

Переделал немного твою программу - теперь все картинки открываются нормально (BTW, чтобы не лезть каждый раз из жопы (ака "Мои документы") до нужных картинок, установи у OpenDialog1 свойство InitialDir в значение '.' (точка) - тогда будет начинать обзор с текущего каталога):

Кусок №1:
CODE
  Pallete: array[1..256] of record
    R, G, B: byte;
  end;
Заменить на:
CODE
  Pallete: array[0..255] of packed record
    R, G, B: byte;
  end;



Кусок №2:
CODE
    for i:=1 to 256 do begin
      TempStream.ReadBuffer(Pallete[i].R,1);
      TempStream.ReadBuffer(Pallete[i].G,1);
      TempStream.ReadBuffer(Pallete[i].B,1);
    end;
Заменить на:
CODE
    TempStream.ReadBuffer(Pallete[0], 256*3);



Кусок №3:
CODE
    for i:=1 to h do begin
      for j:=1 to w do begin
        TempStream.ReadBuffer(b,1);
        Image1.Canvas.Pixels[(j-1),(i-1)]:=((Pallete[b].R*$10000)+(Pallete[b].G*$100)+(Pallete[b].B));
      end;
    end;
Заменить на (RGB, минус один Begin/End и, помимо всего прочего, убрал вычитание единиц на каждом шаге):
CODE
    for i:=0 to h-1 do
      for j:=0 to w-1 do begin
        TempStream.ReadBuffer(b,1);
        Image1.Canvas.Pixels[j,i]:=RGB(Pallete[b].R, Pallete[b].G, Pallete[b].B);
      end;



Ещё добавь после этих строк:
CODE
    Image1.Width:=w;
    Image1.Height:=h;
Вот такие:
CODE
    Image1.Picture.Bitmap.Width:=Image1.Width;
    Image1.Picture.Bitmap.Height:=Image1.Height;

Иначе при попытке открыть сначала "files\piro\SHCKV00.DAT", а потом "files\DATAB.DAT", последний будет у тебя отображаться в маленьком, урезанном окошечке.


И ещё - товарищ Xplorer уже обращал внимание на эту ошибку:
CODE
    Insert('.PAL',pal,Length(pal)-3);
    Delete(pal,Length(pal)-3,4);
Заменить на:
CODE
    pal:=ChangeFileExt(pal, '.PAL');



А вообще - проще сразу с памятью работать, без Image'ов и конвертить эти файлы (.DAT+.PAL) в 256-ти цветовой .BMP.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
Siberian GRemlin
Jun 17 2007, 03:53
Сообщение #3


Advanced Member
***

Группа: CTPAX-X
Сообщений: 538
Регистрация: 4-February 08
Пользователь №: 2
Спасибо сказали: 223 раз(а)



Спасиба!
User is offlineProfile CardPM
Go to the top of the page
+Quote Post
-=CHE@TER=-
Oct 8 2026, 06:10
Сообщение #4


Walter Sullivan
***

Группа: Root Admin
Сообщений: 1,460
Регистрация: 4-February 08
Пользователь №: 3
Спасибо сказали: 332 раз(а)



Наверное, в этой теме будет самое место - про графические ресурсы игр с палитрой.

Часть 1: выбор цвета для прозрачности.
Приходилось мне писать конвертеры для разных игр с 8 BPP форматами графики, т.е. с 256 цветовой палитрой.
Зачастую сжатие спрайтов в таких играх использует простой алгоритм:
- X пикселей пропустить (прозрачность);
- Y пикселей скопировать (рисунок).
На экране это всё очень здорово, а вот когда конвертируешь в какой-нибудь графический формат, то встаёт вопрос, а какой цвет использовать для прозрачности? Цвет-то понятно, фиолетовый (0xFF00FF), при условии, что в игре такого цвета нет, иначе придётся выбирать какой-то другой. В смысле не цвет, а какой индекс из 256 использовать для заливки им прозрачного фона? Обычно как делается: весь рисунок заливается-заполняется этим байтом, а затем, уже поверх фона, идёт декодирование изображения. Зачастую используется индекс 0x00 или 0xFF. Но, и почему собственно я решил это сообщение написать, мне как-то раз попалась игра, которая использовала почти все индексы, в том числе 0x00 и 0xFF, из-за чего у меня прозрачный-фиолетовый стал внезапно появлялся там, где его быть не должно было.
Как быть в таких ситуациях?
Способа два:
1. Переводить всю графику в полноцветное RGB. Тогда не надо будет зависеть от палитры. Минусы очевидны - почти в три раза раздуется размер изображения и редактировать уже будет не так просто (раньше для смены одного цвета можно было тупо цвет в палитре поменять).
2. Найти неиспользуемый индекс из 256 и заливать им, вместо 0x00 или 0xFF.
Я как раз пошёл по второму пути и, проанализировав все файлы, такой индекс нашёл. Уже не помню, что-то там то ли 140, то ли 160, оказался нигде не используемым номером.
Что нужно для второго способа? Нужно поменять декодер изображений - во-первых, не записываете никакие выходные файлы, во-вторых, при каждом запуске читаете файл, например, "usedcols.bin" размером в 256 байт в массив байтов такого же размера. Если такого файла нет, то заполняете массив нулями. Дальше изменяете функцию декодирования, чтобы она непрозрачные байты записывала в этот массив следующим образом:
usedcols[b] = 1;
b - это текущий декодированный непрозрачный байт.
Далее сохраняем перед выходом обновлённый массив usedcols[] в файл "usedcols.bin".
Зачем это нужно? Чтобы можно было свалить все графические файлы в один каталог и запустить:
for %a in (*.spr) do sprtotga.exe %a
Тогда ваша программа пройдётся по всем файлам и сама будет автоматически загружать, обновлять и сохранять массив usedcols[] в соответствующий файл.
А дальше дело техники - открываем файл "usedcols.bin" в любом HEX редакторе и смотрим какой байт всё ещё нулевой. Его смещение от начала файла - и будет номер-индекс цвета для прозрачности. Если их там несколько, то можно будет выбрать любой понравившийся, который менее всего подходит по тону-теме игры.

Часть 2: будьте внимательны к используемым цветам.
Те, кто играл в версию The Neverhood от "Фаргуса", наверное, обратили внимание, что когда вы входите в лифт в коридоре записей, то сцену корёжит. Вот тут даже можно посмотреть как именно: ссылка (на 21:50).
Почему так происходит?
Потому что для создания эффект тени, когда персонаж уходит в затенённое по задумке авторов место, часть цветов в палитре сцены меняется. Но так как у игр работающих в 256 цветах палитра глобальная, то меняется она, естественно, для всей сцены.
Но ведь в оригинале такой проблемы нет и почему там всё было нормально, а в переводе поломано?
Потому что переводчики, когда писали утилиту обратной упаковки графики, выбирали цвета наиболее близкие к тому, что было у них в переведённой картинке, причём брали первые попавшиеся, в результате чего попадали на те индексы, которые менялись динамически.
Как этого избежать?
Запросто - в программе-конвертере предусматриваете три параметра: оригинальная картинка, ваша новая и куда записать сконвертированный результат. В программе берёте оригинальную картинку, анализируете и строите таблицу значений-индексов реально используемых на сцене индексов цветов. И нужные цвета для вашей новой картинки ищите только среди этих индексов - тогда вы 100% гарантированно избежите тех проблем, которые были у "Фаргуса", и не попадёте на номера-индексы цветов, палитра которых меняется. Ну и с файла-оригинала ещё и палитру можно будет взять для этой сцены и другие дополнительные параметры, если это необходимо, перед тем как записывать результат в третий файл-параметр.
Идеальный способ проверки, конечно, это когда вы вытащили что-то из игры, затем не изменяя сразу же сконвертировали результат назад и оно совпало с оригиналом байт-в-байт:
CODE
C:\Work\GameName>fc /b old_file.ext new_file.ext
Сравнение файлов old_file.ext и NEW_FILE.EXT
FC: различия не найдены

Часть 3: когда разработчики подложили свинью.
В самой первой части Carmageddon в палитре используемой в заезде (там ещё есть вторая палитра для меню) есть два абсолютно одинаковых чёрных цвета. Первый имеет индекс 0x00 и используется игрой как прозрачный, а тот, который нужно чтобы был чёрным, но присутствовал на сцене, имеет индекс 0x0F. Не сложно догадаться какой чёрный цвет схватят программы конвертирующие полноцветные изображения в изображения с палитрой. Поэтому фанаты попросили меня не только сделать при конвертировании цвет 0x00 фиолетовым, но и слегка осветлить (RGB: 0x080808) индекс 0x0F, чтобы он был всё ещё достаточно чёрным, но при этом не путался с абсолютно чёрным, который используется для прозрачности (если фиолетовый на него заменили при извлечении). Да, и такая чехарда с цветами-индексами тоже может быть - про это тоже нужно помнить. Для контроля можно написать небольшую утилиту, которая проверяет все цвета в палитре и предупреждает, если найдены абсолютно одинаковые.
User is offlineProfile CardPM
Go to the top of the page
+Quote Post

Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0 -

 



Упрощённая версия Сейчас: 17th October 2026 - 03:50