diff --git a/xcoder/features/sc/__init__.py b/xcoder/features/sc/__init__.py index 2faad0b..25f024c 100644 --- a/xcoder/features/sc/__init__.py +++ b/xcoder/features/sc/__init__.py @@ -54,7 +54,7 @@ def compile_sc( sc.write(struct.pack(" None: - width, height = img.size +def split_image(image: Image.Image) -> Image.Image: + width, height = image.size - loaded_image = img.load() - if loaded_image is None: - raise Exception("loaded_image is None") + chunk_count_x = math.ceil(width / CHUNK_SIZE) + chunk_count_y = math.ceil(height / CHUNK_SIZE) + chunk_count = chunk_count_x * chunk_count_y - loaded_clone = img.copy().load() - if loaded_clone is None: - raise Exception("loaded_clone is None") + split_image_buffers = [] - x_chunks_count = width // CHUNK_SIZE - y_chunks_count = height // CHUNK_SIZE + for chunk_index in range(chunk_count): + chunk_x = (chunk_index % chunk_count_x) * CHUNK_SIZE + chunk_y = (chunk_index // chunk_count_x) * CHUNK_SIZE - pixel_index = 0 + chunk_width = min(width - chunk_x, CHUNK_SIZE) + chunk_height = min(height - chunk_y, CHUNK_SIZE) - for y_chunk in range(y_chunks_count + 1): - for x_chunk in range(x_chunks_count + 1): - for y in range(CHUNK_SIZE): - pixel_y = (y_chunk * CHUNK_SIZE) + y - if pixel_y >= height: - break + chunk = image.crop( + (chunk_x, chunk_y, chunk_x + chunk_width, chunk_y + chunk_height) + ) - for x in range(CHUNK_SIZE): - pixel_x = (x_chunk * CHUNK_SIZE) + x - if pixel_x >= width: - break + split_image_buffers.append(chunk.tobytes("raw")) - _add_pixel( - loaded_image, pixel_index, width, loaded_clone[pixel_x, pixel_y] - ) - pixel_index += 1 + Console.progress_bar(locale.split_pic, chunk_index, chunk_count) - Console.progress_bar(locale.split_pic, y_chunk, y_chunks_count + 1) + return Image.frombuffer( + image.mode, image.size, b"".join(split_image_buffers), "raw" + ) def get_byte_count_by_pixel_type(pixel_type: int) -> int: @@ -136,19 +129,28 @@ def get_format_by_pixel_type(pixel_type: int) -> str: def save_texture(writer: Writer, image: Image.Image, pixel_type: int) -> None: + raw_mode = get_raw_mode(pixel_type) encode_pixel = get_pixel_encode_function(pixel_type) - if encode_pixel is None: - raise Exception(locale.unknown_pixel_type % pixel_type) width, height = image.size pixels = image.getdata() - for y in range(height): - for x in range(width): - # noinspection PyTypeChecker - writer.write(encode_pixel(pixels[y * width + x])) - Console.progress_bar(locale.writing_pic, y, height) + # Some packers for raw_encoder are absent + # https://github.com/python-pillow/Pillow/blob/58e48745cc7b6c6f7dd26a50fe68d1a82ea51562/src/encode.c#L337 + # https://github.com/python-pillow/Pillow/blob/main/src/libImaging/Pack.c#L668 + if raw_mode != image.mode and encode_pixel is not None: + for y in range(height): + for x in range(width): + # noinspection PyTypeChecker + writer.write(encode_pixel(pixels[y * width + x])) + + Console.progress_bar(locale.writing_pic, y, height) + + return + + writer.write(image.tobytes("raw", raw_mode, 0, 1)) + Console.progress_bar(locale.writing_pic, height - 1, height) def transform_image( diff --git a/xcoder/pixel_utils.py b/xcoder/pixel_utils.py index 110fbd3..5f642fe 100644 --- a/xcoder/pixel_utils.py +++ b/xcoder/pixel_utils.py @@ -57,25 +57,13 @@ def _write_rgb565(pixel: PixelChannels) -> bytes: return struct.pack("> 3 | g >> 2 << 5 | r >> 3 << 11) -def _write_luminance8_alpha8(pixel: PixelChannels) -> bytes: - return struct.pack("2B", *pixel[::-1]) - - -def _write_luminance8(pixel: PixelChannels) -> bytes: - return struct.pack("B", pixel) - - _encode_functions: dict[int, EncodeFunction] = { - 0: _write_rgba8, - 1: _write_rgba8, 2: _write_rgba4, 3: _write_rgb5a1, 4: _write_rgb565, - 6: _write_luminance8_alpha8, - 10: _write_luminance8, } -# here is a problem with this names https://github.com/python-pillow/Pillow/pull/8158 +# here is a problem with these names https://github.com/python-pillow/Pillow/pull/8158 _raw_modes: dict[int, RawMode] = { 0: "RGBA", 1: "RGBA",