commit d73a2cd6ac59140b6b5fc9e530cc55f1f3457757 Author: Egor Tsyganchuk Date: Fri Nov 29 18:49:26 2024 +0300 Added scripts for assembling images from `*.c` source files. diff --git a/make_image_from_file.py b/make_image_from_file.py new file mode 100644 index 0000000..60f8577 --- /dev/null +++ b/make_image_from_file.py @@ -0,0 +1,66 @@ +import binascii +from PIL import Image +import sys +import os + +def extract_bytes(input_file): + # Создаем имя для выходного бинарного файла, используя имя входного + base_name = os.path.splitext(input_file)[0] + output_file = base_name + '_output.bin' + + with open(input_file, 'r') as f_in: + data = f_in.read() + + # Список для хранения байтов + byte_array = [] + + # Проходим по строке и извлекаем байты, начинающиеся с '0x' + i = 0 + while i < len(data): + if data[i:i+2] == '0x': # Ищем '0x' + hex_str = data[i+2:i+4] # Берем два символа после '0x' + if len(hex_str) == 2: # Убедимся, что это валидный байт + byte_array.append(binascii.unhexlify(hex_str)) # Преобразуем в байт + i += 4 # Пропускаем этот байт + else: + i += 1 # Пропускаем все остальные символы + + # Записываем полученные байты в новый файл + with open(output_file, 'wb') as f_out: + f_out.write(b''.join(byte_array)) + + print(f"Байты записаны в {output_file}") + return output_file # Возвращаем имя бинарного файла + +def create_image_from_bytes(byte_file, image_file, width, height): + # Читаем байты из файла + with open(byte_file, 'rb') as f: + byte_data = f.read() + + # Переводим данные в список для изменения порядка байтов (R <-> B) + byte_data = bytearray(byte_data) + + # Проходим по данным и меняем местами байты для каналов R и B + for i in range(0, len(byte_data), 4): # шаг 4, потому что каждый пиксель 4 байта + # Меняем местами R и B (преобразуем из BGRA в RGBA) + byte_data[i], byte_data[i+2] = byte_data[i+2], byte_data[i] + + # Преобразуем байты в изображение + image = Image.frombytes('RGBA', (width, height), bytes(byte_data)) + image.save(image_file) + print(f"Изображение сохранено как {image_file}") + +if __name__ == "__main__": + input_file = sys.argv[1] # Путь к текстовому файлу + width = int(sys.argv[2]) # Ширина изображения + height = int(sys.argv[3]) # Высота изображения + + # Извлекаем байты из текстового файла и записываем в бинарный файл + output_file = extract_bytes(input_file) + + # Создаем имя для изображения, используя имя входного файла + base_name = os.path.splitext(input_file)[0] + image_file = base_name + '.png' + + # Создаем изображение из бинарных данных + create_image_from_bytes(output_file, image_file, width, height) diff --git a/parse_c_files_from_dir.py b/parse_c_files_from_dir.py new file mode 100644 index 0000000..44480b7 --- /dev/null +++ b/parse_c_files_from_dir.py @@ -0,0 +1,85 @@ +import os +import re +import argparse +import subprocess + +def extract_byte_array_from_c_file(file_path): + """Извлекает массив байт из C-файла, начиная с '#if LV_COLOR_DEPTH == 32' и заканчивая '#endif', исключая комментарии и строки '#if' и '#endif'.""" + with open(file_path, 'r', encoding='utf-8') as file: + content = file.read() + + # Ищем нужный участок текста между '#if LV_COLOR_DEPTH == 32' и '#endif' + pattern = r'#if LV_COLOR_DEPTH == 32(.*?)#endif' + match = re.search(pattern, content, re.DOTALL) + + if match: + byte_array_content = match.group(1) + + # Удаляем все комментарии (строки, начинающиеся с /* и заканчивающиеся на */) + byte_array_content = re.sub(r'/\*.*?\*/', '', byte_array_content, flags=re.DOTALL) + + # Удаляем саму строку #if LV_COLOR_DEPTH == 32 и #endif + byte_array_content = byte_array_content.strip() + + return byte_array_content + else: + return None + +def extract_image_dimensions(file_path): + """Извлекает размеры изображения (ширину и высоту) из C-файла.""" + with open(file_path, 'r', encoding='utf-8') as file: + content = file.read() + + # Ищем ширину и высоту + width_pattern = r'\.header\.w\s*=\s*(\d+)' + height_pattern = r'\.header\.h\s*=\s*(\d+)' + + width_match = re.search(width_pattern, content) + height_match = re.search(height_pattern, content) + + if width_match and height_match: + width = int(width_match.group(1)) + height = int(height_match.group(1)) + return width, height + else: + return None, None + +def process_directory(directory_path): + """Обрабатывает все C-файлы в указанной директории и сохраняет найденные массивы байт в отдельные файлы.""" + for root, dirs, files in os.walk(directory_path): + for file_name in files: + if file_name.endswith('.c'): + file_path = os.path.join(root, file_name) + + # Извлекаем массив байт + byte_array = extract_byte_array_from_c_file(file_path) + + if byte_array: + # Извлекаем размеры изображения + width, height = extract_image_dimensions(file_path) + + if width is not None and height is not None: + # Создаем новый файл с таким же именем, как у исходного C-файла + output_file_path = os.path.splitext(file_path)[0] + '_byte_array.txt' + with open(output_file_path, 'w', encoding='utf-8') as output_file: + output_file.write(byte_array) + print(f"Массив байт для файла {file_name} сохранен в {output_file_path}") + + # Запускаем внешний скрипт для обработки изображения + subprocess.run(['python', 'make_image_from_file.py', output_file_path, str(width), str(height)]) + else: + print(f"Не удалось извлечь размеры изображения из файла {file_name}") + +def main(): + # Создание парсера аргументов + parser = argparse.ArgumentParser(description="Извлекает массив байт из C-файлов и сохраняет их в отдельные текстовые файлы.") + parser.add_argument('directory', type=str, help="Путь к директории с C-файлами") + + # Парсинг аргументов + args = parser.parse_args() + + # Обработка указанной директории + process_directory(args.directory) + +if __name__ == '__main__': + main()