Добро пожаловать, гость ( Вход | Регистрация )
![]() ![]() |
| Siberian GRemlin |
Jun 16 2007, 04:51
Сообщение
#1
|
|
Advanced Member ![]() ![]() ![]() Группа: CTPAX-X Сообщений: 538 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 223 раз(а) |
Уважаемые, объясните что к чему. Вроде, всё правильно делаю, а изображение похоже с косяками.
http://slil.ru/24516685 - исходник + примеры из игры Earth 2140 |
| -=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 Заменить на (RGB, минус один Begin/End и, помимо всего прочего, убрал вычитание единиц на каждом шаге):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; 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. |
| Siberian GRemlin |
Jun 17 2007, 03:53
Сообщение
#3
|
|
Advanced Member ![]() ![]() ![]() Группа: CTPAX-X Сообщений: 538 Регистрация: 4-February 08 Пользователь №: 2 Спасибо сказали: 223 раз(а) |
Спасиба!
|
| -=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, чтобы он был всё ещё достаточно чёрным, но при этом не путался с абсолютно чёрным, который используется для прозрачности (если фиолетовый на него заменили при извлечении). Да, и такая чехарда с цветами-индексами тоже может быть - про это тоже нужно помнить. Для контроля можно написать небольшую утилиту, которая проверяет все цвета в палитре и предупреждает, если найдены абсолютно одинаковые. |
![]() ![]() |
| Упрощённая версия | Сейчас: 17th October 2026 - 03:51 |