def load_file(self, index): file = self._files[index] if file['data'] is None: if file['size'] != 0: file['data'] = IOHelper.read_range(self._io, file['offset'], file['size']) else: print('size is zero, read all data.') file['data'] = IOHelper.read_range(self._io, file['offset'], -1) return file['data']
def _png_to_nximg(data, image_format): data_nximg = bytes() with BytesIO(data) as io_png: with BytesIO() as io_nximg: png = PngImageFile(io_png) w, h = png.width, png.height if image_format == IMAGE_FORMAT_1555: for y in range(h): for x in range(w): [r, g, b, a] = png.getpixel((x, y)) IOHelper.write_struct(io_nximg, "<2B", *NXColor.to_1555(r, g, b, a)) elif image_format == IMAGE_FORMAT_4444: for y in range(h): for x in range(w): [r, g, b, a] = png.getpixel((x, y)) IOHelper.write_struct(io_nximg, "<2B", *NXColor.to_4444(r, g, b, a)) elif image_format == IMAGE_FORMAT_8888: for y in range(h): for x in range(w): [r, g, b, a] = png.getpixel((x, y)) IOHelper.write_struct(io_nximg, "<4B", b, g, r, a) else: raise Exception('Unsupport image format: %s' % image_format) data_nximg = IOHelper.read_range(io_nximg) return data_nximg, w, h
def load_file(self, index): file = self._files[index] if file['data'] is None: file['data'] = IOHelper.read_range(self._io, file['offset'], file['size']) return file['data']
def raw_to_png(data, w, h, rotate=0): raw_image = Image.frombytes('RGBA', (w, h), data) if rotate == 1: raw_image = raw_image.transpose(Image.ROTATE_90) with BytesIO() as io_png: raw_image.save(io_png, 'png') data_png = IOHelper.read_range(io_png) return data_png
def _indexes_to_raw(data, color_board): with BytesIO(data) as io_indexes: with BytesIO() as io_raw: temp = IOHelper.read_struct(io_indexes, '<B', False) while temp is not None: [index] = temp IOHelper.write_struct(io_raw, '<4B', *color_board[index]) temp = IOHelper.read_struct(io_indexes, '<B', False) data_raw = IOHelper.read_range(io_raw) return data_raw
def load_image_map(self, index): io = self._io map_image = self._map_images[index] if map_image['data'] is not None: return map_image['data'] data = IOHelper.read_range(io, map_image['offset'], map_image['data_size']) data = zlib.decompress(data) map_image['data'] = data return data
def save(self, io=None): # load all file data. self.load_all() files = self._files if io is None: io = self._io # clean file. io.seek(0) io.truncate() head_data = b'' # build head in memory. with BytesIO() as io_head: IOHelper.write_ascii_string(io_head, FILE_MAGIC) count = len(files) IOHelper.write_struct(io_head, 'i', count) # count file offset. # magic(16) + count(4) + info(264 * n) + hash(32) offset = 52 + count * 264 for file in files: file['offset'] = offset file['size'] = len(file['data']) IOHelper.write_struct(io_head, '<2i', file['offset'], file['size']) if isinstance(file['name'], str): name_data = file['name'].encode(encoding='euc_kr') elif isinstance(file['name'], bytes): name_data = file['name'] else: raise Exception('Filename type Error: %s(%s)' % (file['name'], type(file['name']))) name = NPK._decrypt_name(name_data) io_head.write(name) offset += file['size'] head_data = IOHelper.read_range(io_head) io.write(head_data) # write hash. io.write( hashlib.sha256(head_data[:len(head_data) // 17 * 17]).digest()) for file in files: io.seek(file['offset']) io.write(file['data'])
def data(self, index): if index < len(self._files): file = self._files[index] # type: dict if file['data'] is None: if not file['is_zip']: data = IOHelper.read_range(self._io, file['offset'], file['data_size']) file['data'] = data else: raise Exception('Unsupport File.') else: data = file['data'] return data
def dds_to_png(data, box=None, rotate=0): with BytesIO(data) as io_dds: map_image = DdsImageFile(io_dds) if box is not None: map_image = map_image.crop(box) if rotate == 1: map_image = map_image.transpose(Image.ROTATE_90) with BytesIO() as io_png: map_image.save(io_png, 'png') data_png = IOHelper.read_range(io_png) return data_png
def load_image(self, index): io = self._io image = self._images[index] if image['format'] == IMAGE_FORMAT_LINK: return None if image['data'] is not None: return image['data'] data = IOHelper.read_range(io, image['offset'], image['size']) if image['extra'] == IMAGE_EXTRA_ZLIB: data = zlib.decompress(data) elif image['extra'] != IMAGE_EXTRA_NONE: raise Exception('Unknown Extra Type.', image['extra']) image['data'] = data return data
def save(self, io=None): # load all file data. self.load_all() files = self._files if io is None: io = self._io # clean file. io.seek(0) io.truncate() # build head in memory. with BytesIO() as io_head: IOHelper.write_ascii_string(io_head, FILE_MAGIC) count = len(files) IOHelper.write_struct(io_head, 'i', count) # count file offset. # magic(16) + count(4) + info(264 * n) + hash(32) offset = 52 + count * 264 for file in files: IOHelper.write_struct(io_head, '<2i', file['offset'], file['size']) name = NPK._decrypt_name(file['name'].encode(encoding='ascii')) io_head.write(name) offset += file['size'] head_data = IOHelper.read_range(io_head) io.write(head_data) # write hash. io.write( hashlib.sha256(head_data[:len(head_data) // 17 * 17]).digest()) for file in files: io.seek(file['offset']) io.write(file['data'])
def print_exception(type, value, tb): with StringIO() as io: traceback.print_exception(type, value, tb, file=io) err_str = IOHelper.read_range(io) print(err_str) QMessageBox.warning(None, '错误:', err_str)
def _nximg_to_raw(data, image_format, w=None, box=None): data_raw = bytes() ps = PIX_SIZE[image_format] with BytesIO(data) as io_nximg: with BytesIO() as io_raw: if image_format == IMAGE_FORMAT_1555: if box is not None and w is not None: [left, top, right, bottom] = box for y in range(top, bottom): o = y * w * ps for x in range(left, right): io_nximg.seek(o + x * ps) temp = IOHelper.read_struct( io_nximg, '<2B', False) if temp is not None: [v1, v2] = temp IOHelper.write_struct( io_raw, '<4B', *NXColor.from_1555(v1, v2)) else: temp = IOHelper.read_struct(io_nximg, '<2B', False) while temp is not None: [v1, v2] = temp IOHelper.write_struct(io_raw, '<4B', *NXColor.from_1555(v1, v2)) temp = IOHelper.read_struct(io_nximg, '<2B', False) elif image_format == IMAGE_FORMAT_4444: if box is not None and w is not None: [left, top, right, bottom] = box for y in range(top, bottom): o = y * w * ps for x in range(left, right): io_nximg.seek(o + x * ps) temp = IOHelper.read_struct( io_nximg, '<2B', False) if temp is not None: [v1, v2] = temp IOHelper.write_struct( io_raw, '<4B', *NXColor.from_4444(v1, v2)) else: temp = IOHelper.read_struct(io_nximg, '<2B', False) while temp is not None: [v1, v2] = temp IOHelper.write_struct(io_raw, '<4B', *NXColor.from_4444(v1, v2)) temp = IOHelper.read_struct(io_nximg, '<2B', False) elif image_format == IMAGE_FORMAT_8888: if box is not None and w is not None: [left, top, right, bottom] = box for y in range(top, bottom): o = y * w * ps for x in range(left, right): io_nximg.seek(o + x * ps) temp = IOHelper.read_struct( io_nximg, '<4B', False) if temp is not None: [b, g, r, a] = temp IOHelper.write_struct( io_raw, '<4B', r, g, b, a) else: temp = IOHelper.read_struct(io_nximg, '<4B', False) while temp is not None: [b, g, r, a] = temp IOHelper.write_struct(io_raw, '<4B', r, g, b, a) temp = IOHelper.read_struct(io_nximg, '<4B', False) else: raise Exception('Unsupport Image Format.', image_format) data_raw = IOHelper.read_range(io_raw) return data_raw
def save(self, io=None): self.load_all() images = self._images color_board = self._color_board color_boards = self._color_boards map_images = self._map_images version = self._version images_data = [] # compress data, get size, add to data_list. if version == FILE_VERSION_5: for map_image in sorted(map_images): data = map_image['data'] map_image['raw_size'] = len(data) data = zlib.compress(data) map_image['data_size'] = len(data) images_data.append(data) else: for image in images: if image['format'] != IMAGE_FORMAT_LINK: data = image['data'] if image['extra'] == IMAGE_EXTRA_ZLIB or image[ 'extra'] == IMAGE_EXTRA_MAP_ZLIB: data = zlib.compress(data) image['size'] = len(data) images_data.append(data) images_size = self._save_count_images_size() file_size = self._save_count_file_size(images_size, images_data) if io is None: io = self._io io.seek(0) io.truncate() with BytesIO() as io_head: if version == FILE_VERSION_1: IOHelper.write_ascii_string(io_head, FILE_MAGIC_OLD) # TODO: unknown, now be zero. IOHelper.write_struct(io_head, 'h', 0) else: # images_size IOHelper.write_ascii_string(io_head, FILE_MAGIC) IOHelper.write_struct(io_head, 'i', images_size) # keep, version, img_count IOHelper.write_struct(io_head, '<3i', 0, version, len(images)) is_ver5 = version == FILE_VERSION_5 if is_ver5: # map_count, file_size IOHelper.write_struct(io_head, '<2i', len(map_images), file_size) if version == FILE_VERSION_4 or is_ver5: # color_count IOHelper.write_struct(io_head, 'i', len(color_board)) for color in color_board: # color IOHelper.write_struct(io_head, '<4B', *color) if is_ver5: for map_image in map_images: IOHelper.write_struct(io_head, '<7i', map_image['keep'], map_image['format'], map_image['index'], map_image['data_size'], map_image['raw_size'], map_image['w'], map_image['h']) if version == FILE_VERSION_6: # color_board count. IOHelper.write_struct(io_head, 'i', len(color_boards)) for color_board_v6 in color_boards: # color_count IOHelper.write_struct(io_head, 'i', len(color_board_v6)) for color in color_board_v6: # color IOHelper.write_struct(io_head, '<4B', *color) for image in images: # format IOHelper.write_struct(io_head, 'i', image['format']) if image['format'] == IMAGE_FORMAT_LINK: # link IOHelper.write_struct(io_head, 'i', image['link']) else: # extra, w, h, size, x, y, mw, mh IOHelper.write_struct(io_head, '<8i', image['extra'], image['w'], image['h'], image['size'], image['x'], image['y'], image['mw'], image['mh']) if image['extra'] == IMAGE_EXTRA_MAP_ZLIB: # keep_1, map_index, left, top, right, bottom, rotate IOHelper.write_struct(io_head, '<7i', image['keep_1'], image['map_index'], image['left'], image['top'], image['right'], image['bottom'], image['rotate']) head_data = IOHelper.read_range(io_head) io.write(head_data) for data in images_data: io.write(data)