# TENTO SKRIPT NENÍ URČEN PRO ŘEŠENÍ, SLOUŽÍ POUZE JAKO KONTROLA # AUTOR SKRIPTU NERUČÍ ZA POUŽITÍ SKRIPTU ČI NESPRÁVNOST JEHO VÝSTUPU import os from PIL import Image # PACKAGE 'pillow' REQUIRED color_map_types = { "00": "soubor s obrázkem neobsahuje mapu barev", "01": "je přítomna mapa barev" } image_types = { "00": "nejsou přítomna žádná obrazová data", "01": "nekomprimovaný obraz s barevným mapováním", "02": "nekomprimovaný obraz v True Color", "03": "nekomprimovaný černobílý obraz (ve stupních šedi)" } start_pixel_locations = { "00": "Dole vlevo", "01": "Nahoře vlevo", "10": "Dole vpravo", "11": "Nahoře vpravo" } class Header: COLOR_MAP_TYPE = 0 IMAGE_TYPE = 1 MAP_START_INDEX = (2, 3+1) MAP_SIZE = (4, 5+1) MAP_OTHER = 6 WIDTH = (7, 8+1) HEIGHT = (9, 10+1) BITS_PER_PIXEL = 11 DESCRIPTOR = 12 ALPHA_DEPTH = (0, 3+1) START_PIXEL_LOCATION = (4, 5+1) DATA_OFFSET = 13 def raw2hex(input_raw: str) -> str: if len(input_raw) % 2 != 0: raise ValueError("Raw bajty nejsou v sudém počtu: " + input_raw) byte_list = [input_raw[j:j + 2] for j in range(0, len(input_raw), 2)] output_hex = ''.join(reversed(byte_list)) return output_hex def hex2dec(input_hex: str) -> str: return str(int(input_hex, 16)) def hex2bin(input_hex: str) -> list[str]: value = int(input_hex, 16) bin_str = format(value, f'0{len(input_hex) * 4}b') bin_arr = [str(bit) for bit in bin_str] bin_arr.reverse() return bin_arr def bin2dec(input_bin: str) -> str: dec = int(input_bin.strip(), 2) return str(dec) def hex2ascii(input_hex: str) -> str: return bytes.fromhex(input_hex).decode("ascii") def hex2date(input_hex: str) -> str: def read_field(start: int) -> int: field_hex = input_hex[start:start + 4] return int.from_bytes(bytes.fromhex(field_hex), byteorder="little") month = read_field(0) day = read_field(4) year = read_field(8) hour = read_field(12) minute = read_field(16) second = read_field(20) return f"{day:02d}. {month:02d}. {year}, {hour:02d}:{minute:02d}:{second:02d}" def hex2ansi(input_hex: str) -> str: if len(input_hex) != 6: raise ValueError("Barvy raw bajtů nejsou ve skupinách 3 bajtů: " + input_hex) r = int(input_hex[0:2], 16) g = int(input_hex[2:4], 16) b = int(input_hex[4:6], 16) return f"\033[38;2;{r};{g};{b}m" def get_color_map_type(input_hex: str) -> str: return color_map_types.get(input_hex, "vyhrazeno pro jiné účely") def get_image_type(input_hex: str) -> str: return image_types.get(input_hex, "vyhrazeno pro jiné účely") def get_start_pixel_location(input_bin: str) -> str: return start_pixel_locations.get(input_bin, "Neznámá lokace prvního pixel") def write_png(output_path, width, height, input_bytes, data_offset): pixel_data = [] for i in range(width * height): base = data_offset + i * 3 b = int(input_bytes[base + 0], 16) g = int(input_bytes[base + 1], 16) r = int(input_bytes[base + 2], 16) pixel_data.extend([r, g, b]) pixel_bytes = bytes(pixel_data) img = Image.frombytes("RGB", (width, height), pixel_bytes) img.save(output_path) print("Obrázek uložen do: " + output_path) choice = input("1: Zadat raw bajty (Doporuečno)\n2: Zadat název souboru s raw bajty\n3: Zadat název souboru .pif (papulastic-image-format)\n") input_bytes = [] data = "" if choice == 1: user_input = input("Zadjete raw bajty: ") data = user_input.replace(" ", "") elif choice == 2: user_input = input("Cesta k souboru s raw batjy: ") input_path = os.path.expanduser(user_input) with open(input_path, "r") as f: data = f.read().strip().replace(" ", "") else: user_input = input("Cesta k souboru .pif: ") input_path = os.path.expanduser(user_input) with open(input_path, "rb") as f: raw_bytes = f.read().strip() input_bytes = [f"{b:02x}" for b in raw_bytes] if choice == 1 or choice == 2: for i in range(0, len(data), 2): input_bytes.append(data[i:i + 2]) if len(input_bytes) > 0: # COLOR MAP TYPE color_map_type = input_bytes[Header.COLOR_MAP_TYPE] print("Typ barevné mapy: " + get_color_map_type(raw2hex(color_map_type)) + " (0x" + raw2hex(color_map_type) + ")") # IMAGE TYPE image_type = input_bytes[Header.IMAGE_TYPE] print("Komprese a typ obrázku: " + get_image_type(raw2hex(image_type)) + " (0x" + raw2hex(image_type) + ")\n") # COLOR MAP SPECS print("specifikace barevné palety: (Pokud je pole Color map type nastaveno na nulu (žádná mapa barev neexistuje), pak by těchto 5 bajtů mělo být nastaveno na nulu.)") if color_map_type == "00": print("Žádná mapa neexistuje, bajty by měly být nula") else: print("Mapa existuje") # MAP START INDEX start, end = Header.MAP_START_INDEX map_start_index = "".join(input_bytes[start:end]) print("\tIndex první položky barevné mapy: " + hex2dec(raw2hex(map_start_index)) + " (0x" + raw2hex(map_start_index) + ")") # MAP SIZE start, end = Header.MAP_SIZE map_size = "".join(input_bytes[start:end]) print("\tDélka barevné mapy: " + hex2dec(raw2hex(map_size)) + " (0x" + raw2hex(map_size) + ")") # MAP OTHER map_other = input_bytes[Header.MAP_OTHER] print("\tDoplňkové údaje k barevné mapě: Není definováno (0x" + raw2hex(map_other) + ")\n") # IMAGE SPECS print("Specifikace rozměrů obrázku:") # WIDTH start, end = Header.WIDTH width = "".join(input_bytes[start:end]) print("\tŠířka obrázku v pixelech: " + hex2dec(raw2hex(width)) + "px (0x" + raw2hex(width) + ")") # HEIGHT start, end = Header.HEIGHT height = "".join(input_bytes[start:end]) print("\tVýška obrázku v pixelech: " + hex2dec(raw2hex(height)) + "px (0x" + raw2hex(height) + ")") size = int(hex2dec(raw2hex(width))) * int(hex2dec(raw2hex(height))) # BITS/PIXEL bits_per_pixel = input_bytes[Header.BITS_PER_PIXEL] print("\tHloubka pixelu (bity na pixel): " + hex2dec(raw2hex(bits_per_pixel)) + " bitů na pixel (0x" + raw2hex(bits_per_pixel) + ")") # DESCRIPTOR descriptor_bits = hex2bin(raw2hex(input_bytes[Header.DESCRIPTOR])) print("\tDeskriptor obrazu: (0b" + "".join(descriptor_bits) + ")") # ALPHA DEPTH start, end = Header.ALPHA_DEPTH alpha_depth = "".join(descriptor_bits[start:end]) print("\t\tHloubka alfa kanálu: " + bin2dec(alpha_depth) + " (0b" + alpha_depth + ")") # START PIXEL LOCATION start, end = Header.START_PIXEL_LOCATION start_pixel_location = "".join(descriptor_bits[start:end]) print("\t\tPočátek obrazu (kde leží první pixel): " + get_start_pixel_location(start_pixel_location) + " (0b" + start_pixel_location + ")") # UNUSED print("\t\tBity 6 a 7 nejsou definovány") # DATA choice = input("1: Vypsat data do konzole (Doporučeno pouze pro malé obrázky)\n2: Uložit obrázek do PNG souboru\n") if choice == 1: print("Data:") data = "" for i in range(0, int(hex2dec(raw2hex(height)))): for j in range(0, int(hex2dec(raw2hex(width)))): byte_list = input_bytes[Header.DATA_OFFSET + (i * width + j) * 3 : Header.DATA_OFFSET + (i * width + j) * 3 + 3] data += hex2ansi(raw2hex("".join(byte_list))) data += "#" + raw2hex("".join(byte_list)) + " \033[0m" data += "\n" print(data) else: user_input = input("Zadejte cestu pro výsledný soubor PNG obrázku: ") output_path = os.path.expanduser(user_input) write_png(output_path, int(hex2dec(raw2hex(width))), int(hex2dec(raw2hex(height))), input_bytes, Header.DATA_OFFSET) offset = Header.DATA_OFFSET + size * 3 # OTHER DATA print("Rozšiřující data:") # INITIALS start, end = (offset, offset + 2) print("\tIniciály autora: " + hex2ascii("".join(input_bytes[start:end])) + " (0x" + "".join(input_bytes[start:end]) + ")") # DATE start, end = (offset + 3, offset + 15) date = input_bytes[start:end] print("\t\033[31mDatum (čas pořízení): " + hex2date("".join(input_bytes[start:end])) + " (0b" + "".join(date) + ")\033[0m\n") # FOOTER print("Patička:") # SIGNATURE start, end = (offset + 15, offset + 31) signature = input_bytes[start:end] print("\t\033[31mPodpis: " + hex2ascii("".join(signature)) + " (0x" + "".join(signature) + ")\033[0m") # ALWAYS DOT always_dot = input_bytes[end] print("\tRezervovaný znak: " + hex2ascii(always_dot) + " (0x" + always_dot + ")") always_zero = input_bytes[end + 1] print("\tBinární nula: 0x" + always_zero) print("\n\nDůležité informace zaznačeny barevně")