def main(): print(sys.argv) start_time = time.time() if len(sys.argv) != 5: printUsage() if sys.argv[1] == "compress": compress(filename=sys.argv[2], path_to_dir=sys.argv[3], output_dir=sys.argv[4]) end_information(sys.argv[3] + sys.argv[2], sys.argv[4] + sys.argv[2]) elif sys.argv[1] == "decompress": decompress(filename=sys.argv[2], path_to_dir=sys.argv[3], output_dir=sys.argv[4]) else: printUsage() print(f"{sys.argv[1]} took {time.time() - start_time} seconds.")
def tests(): #files = ['pan-tadeusz-czyli-ostatni-zajazd-na-litwie.txt', # 'test1.bin', # 'test2.bin', # 'test3.bin'] files = ['my_test5.txt'] for filename in files: start_time = time.time() print(f"Start compressing {filename}") compress(filename, path_to_dir="files/", output_dir="compressed/") compress_time = time.time() end_information("files/" + filename, "compressed/" + filename) print( f"Compression of {filename} took {round(compress_time - start_time,2)} seconds" ) decompress(filename, path_to_dir="compressed/", output_dir="decompressed/") decompress_time = time.time() print( f"Decompression of {filename} took {round(decompress_time - compress_time, 2)} seconds" )
return data def img_palette_to_gba(img): formatted = format_img_palette(img) return pal_to_gba(formatted) def pal_to_gba(palette): data = b'' for color in palette: r, g, b = color r >>= 3 g >>= 3 b >>= 3 data += (r | (g << 5) | (b << 10)).to_bytes(2, 'little') return data if __name__ == '__main__': import lz77 img = Image.open('../char.png') with open('../bpre.gba', 'rb+') as f: d = img_to_gba_16colors(img) f.seek(0x800000) f.write(lz77.compress(d)) f.seek(0x900000) d = format_img_palette(img) f.write(lz77.compress(pal_to_gba(d)))
import lz77 tests = [{ "message": "кибернетики", "buffer_size": 4, "dict_size": 12, "result": [(0, 0, 'к'), (0, 0, 'и'), (0, 0, 'б'), (0, 0, 'е'), (0, 0, 'р'), (0, 0, 'н'), (3, 1, 'т'), (7, 1, 'к'), (2, 1, '')] }, { "message": "аааааааааааа", "buffer_size": 4, "dict_size": 12, "result": [(0, 0, 'а'), (1, 1, 'а'), (3, 3, 'а'), (4, 4, 'а')] }] for test in tests: result = lz77.compress(test['message'], test['buffer_size'], test['dict_size']) print(result) assert result == test['result'] message = lz77.decompress(test['result']) print(message) assert message == test['message'] print('===========================')
pattern, color = convert_tile(im, x * 8, y * 8) patterns.extend(pattern) colors.extend(color) return patterns, colors def print_static_table(data, name): print("static const uint8_t {0}[] = {{".format(name), end='') print(", ".join([str(row) for row in data]), end='') print("};") if len(sys.argv) < 2: sys.exit("Missing arguments") # convert screen name = os.path.splitext(os.path.basename(sys.argv[1]))[0] im = Image.open(sys.argv[1]) assert (im.size == (128, 128) or im.size == (256, 192)) assert (im.mode == "P") patterns, colors = convert_screen(im) sys.stderr.write("pat_{0}\n".format(name)) cpatterns = compress(patterns) sys.stderr.write("col_{0}\n".format(name)) ccolors = compress(colors) # export table print_static_table(cpatterns, "pat_" + name) print("") print_static_table(ccolors, "col_" + name)
parts_data[parts_offsets.index(offset)] = data updated_parts.append(offset) # Write new parts' data print parts_offsets bac.seek(data_offset + 4) bac.truncate() new_offsets = [] for index, data in enumerate(parts_data): new_offsets.append(bac.tell() - data_offset) # bac.write(pack('<I', len(data) << 8)) # bac.write(data) compress(data, bac) # try: # if bac.tell() - data_offset < parts_offsets[index + 1]: # bac.seek(parts_offsets[index + 1] + data_offset) # except IndexError: # pass # while bac.tell() % 4: # bac.write('\xff') print new_offsets # Calculate and write block size block_size = bac.tell() - data_offset bac.seek(data_offset)
def update(self, image, vram_offset=0, empty=False, compress=True): if not vram_offset: vram_offset = getattr(self, 'vram_offset', 0) # First tile - empty tile? if empty: empty = [0] * (8 * 8) tiles = [empty] else: tiles = [] mappings = [] reused = 0 transforms = ( (None, False, False), (Image.FLIP_LEFT_RIGHT, True, False), (Image.FLIP_TOP_BOTTOM, False, True), (Image.ROTATE_180, True, True), ) # Iterate over top-left coordinates of each tile and split image to 8x8 tiles for y in range(0, image.size[1], 8): for x in range(0, image.size[0], 8): # Crop image to 8x8 tile tile = image.crop((x, y, x + 8, y + 8)) # Try to find tile duplicates, fliping horizontally/vertically/both if necessary for method, flip_h, flip_v in transforms: if method: transposed = tile.transpose(method) else: transposed = tile data = list(transposed.getdata()) # Try to tile duplicate try: n = tiles.index(data) except ValueError: pass else: mappings.append((n, flip_h, flip_v)) reused += 1 break else: data = list(tile.getdata()) n = len(tiles) tiles.append(data) mappings.append((n, False, False)) #assert reused + len(tiles) == len(mappings) + 1 print '{} tiles reused, {} in result'.format(reused, len(tiles), len(mappings)) # Now try to update bbg file itself bbg = self.bbg (size, data_offset, mappings_offset, palette_offset, color_format, row_len, rows_n, bbg_palette_index, unknown) = self.header # Write tile data data_offset = 0x20 bbg.seek(data_offset) # FIXME: Need to implement LZ77 compression if color_format == 1: data_length = len(tiles) * (8 * 8 / 2) else: data_length = len(tiles) * (8 * 8) data = [] palette_indexes = [] for tile in tiles: if color_format == 1: # Hack for 4 bpp images with multiple palettes palette_index = tile[0] // 16 palette_indexes.append(palette_index) # Store two pixels of tile as one for first, second in izip_longest(*[iter(tile)] * 2): first %= 16 second %= 16 value = (second << 4) | first data.append(chr(value)) else: data += map(chr, tile) assert len(data) == data_length if compress: lz77.compress(data, bbg) else: bbg.write(pack('<i', data_length << 8)) bbg.write(''.join(data)) # Write mappings mappings_offset = bbg.tell() mappings_length = len(mappings) * 2 bbg.write(pack('<i', mappings_length << 8)) palette_index = bbg_palette_index >> 4 mappings_data = [] for n, flip_h, flip_v in mappings: # Calculate vram tile offset value = n + vram_offset # Add palette index #value |= bbg_palette_index << 8# 12 value |= (palette_index + palette_indexes[n]) << 12 # Set flip_h and flip_v flags value |= flip_h << 10 value |= flip_v << 11 # Pack value value = pack('<H', value) mappings_data.append(value) assert len(mappings_data) * 2 == mappings_length bbg.write(''.join(mappings_data)) # Write palette palette_offset = bbg.tell() if self.palette_data: bbg.write(pack('<i', len(self.palette_data) << 8)) bbg.write(self.palette_data) else: bbg.write('\x00' * 4) # Write header size = bbg.tell() bbg.seek(0) bbg.write('BBG\00') row_len = image.size[0] / 8 rows_n = image.size[1] / 8 self.header = BBGHeader(size, data_offset, mappings_offset, palette_offset, color_format, row_len, rows_n, bbg_palette_index, unknown) #unknown = 1 #bbg.write(pack('<5i2h', size, data_offset, mappings_offset, palette_offset, unknown, row_len, rows_n)) bbg.write(pack('<5i4h', *self.header))