Files
P2EP_Export/UnRLE/0754_NICHIDUNG/extract.py
2025-12-08 20:28:56 +05:00

137 lines
5.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import struct
import os
import sys
from PIL import Image
def extract_textures_from_file(filename, output_dir="textures"):
"""
Извлекает текстуры из файла в отдельные PNG файлы с индексированными цветами
"""
# Создаем директорию для выходных файлов
os.makedirs(output_dir, exist_ok=True)
# Читаем файл
with open(filename, 'rb') as f:
fil = f.read()
# Получаем список смещений текстур
tx_offsets = []
first_addr = struct.unpack('<I', fil[0:4])[0]
tx_offsets.append(first_addr)
reader = 4
while reader < first_addr:
addr = struct.unpack('<I', fil[reader:reader+4])[0]
if addr == 0:
break
tx_offsets.append(addr)
reader += 4
print(f"Найдено {len(tx_offsets)} текстурных блоков")
# Обрабатываем каждую текстуру
for a in range(len(tx_offsets) - 1):
try:
reader = tx_offsets[a]
# Читаем CLUT и информацию об изображении
clut_mode = struct.unpack('<I', fil[reader:reader+4])[0]
image_mode = struct.unpack('<I', fil[reader+4:reader+8])[0]
reader += 8
# Читаем CLUT (палитру цветов)
clut_size = struct.unpack('<I', fil[reader:reader+4])[0]
clut_x = struct.unpack('<H', fil[reader+4:reader+6])[0]
clut_y = struct.unpack('<H', fil[reader+6:reader+8])[0]
clut_w = struct.unpack('<H', fil[reader+8:reader+10])[0]
clut_h = struct.unpack('<H', fil[reader+10:reader+12])[0]
reader += 12
# Читаем данные палитры
current_clut = []
clut_data_remains = clut_size - 12
while clut_data_remains > 0:
color_code = struct.unpack('<H', fil[reader:reader+2])[0]
current_clut.append(color_code)
clut_data_remains -= 2
reader += 2
# Читаем информацию об изображении
image_size = struct.unpack('<I', fil[reader:reader+4])[0]
image_x = struct.unpack('<H', fil[reader+4:reader+6])[0] * 2
image_y = struct.unpack('<H', fil[reader+6:reader+8])[0] - 256
image_w = struct.unpack('<H', fil[reader+8:reader+10])[0] * 2
image_h = struct.unpack('<H', fil[reader+10:reader+12])[0]
reader += 12
print(f"Текстура {a}: {image_w}x{image_h}, CLUT: {len(current_clut)} цветов")
# Создаем палитру для PIL
palette = []
for color_code in current_clut:
# Конвертируем из формата PS1 (15-bit) в 24-bit RGB
r = (color_code & 0x1F) * 8
g = ((color_code & 0x3E0) >> 5) * 8
b = ((color_code & 0x7C00) >> 10) * 8
palette.extend([r, g, b])
# Дополняем палитру до 256 цветов (если нужно)
while len(palette) < 768: # 256 цветов * 3 канала
palette.append(0)
# Создаем изображение с индексированными цветами
img_data = []
image_data_remains = image_size - 12
for y in range(image_h):
row = []
for x in range(image_w):
if image_data_remains > 0:
color_index = fil[reader]
row.append(color_index)
reader += 1
image_data_remains -= 1
else:
row.append(0) # Заполняем нулями если данные закончились
img_data.append(row)
# Создаем изображение из данных
img = Image.new('P', (image_w, image_h))
# Заполняем пиксели
for y in range(image_h):
for x in range(image_w):
if y < len(img_data) and x < len(img_data[y]):
img.putpixel((x, y), img_data[y][x])
# Устанавливаем палитру
img.putpalette(palette)
# Сохраняем как PNG
output_filename = os.path.join(output_dir, f"texture_{a:03d}.png")
img.save(output_filename, 'PNG')
print(f"Сохранено: {output_filename}")
except Exception as e:
print(f"Ошибка при обработке текстуры {a}: {e}")
continue
def main():
if len(sys.argv) != 2:
print("Использование: python extract.py <имя_файла>")
sys.exit(1)
filename = sys.argv[1]
if not os.path.exists(filename):
print(f"Файл {filename} не найден!")
sys.exit(1)
print(f"Обрабатываю файл: {filename}")
extract_textures_from_file(filename)
print("Готово!")
if __name__ == "__main__":
main()