Skip to content

Commit 43ea81b

Browse files
Merge pull request #34 from xcoder-tool/texture-saving
refactor(texture): saving texture with tobytes, splitting optimized
2 parents 9116a05 + c15bcf3 commit 43ea81b

File tree

4 files changed

+50
-62
lines changed

4 files changed

+50
-62
lines changed

xcoder/features/sc/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ def compile_sc(
5454
sc.write(struct.pack("<BIBHH", file_type, file_size, pixel_type, width, height))
5555

5656
if file_type in (27, 28):
57-
split_image(sheet)
57+
sheet = split_image(sheet)
5858

5959
save_texture(sc, sheet, pixel_type)
6060
print()

xcoder/features/sc/decode.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,8 @@ def decode_textures_only():
3838
output_folder, base_name
3939
)
4040

41-
_save_meta_file(
42-
swf, objects_output_folder, base_name.rsplit("_", 1)[0], signature
43-
)
4441
_save_textures(swf, objects_output_folder, base_name)
42+
_save_meta_file(swf, objects_output_folder, base_name, signature)
4543
except Exception as exception:
4644
logger.exception(
4745
locale.error
@@ -77,8 +75,8 @@ def decode_and_render_objects():
7775
output_folder, base_name
7876
)
7977

80-
_save_textures(swf, objects_output_folder / "textures", base_name)
8178
render_objects(swf, objects_output_folder)
79+
_save_textures(swf, objects_output_folder / "textures", base_name)
8280
_save_meta_file(swf, objects_output_folder, base_name, signature)
8381
except Exception as exception:
8482
logger.exception(

xcoder/images.py

Lines changed: 46 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66
if TYPE_CHECKING:
77
from PIL._imaging import PixelAccess # type: ignore[reportPrivateImportUsage]
88

9-
from .bytestream import Reader, Writer
10-
from .console import Console
11-
from .localization import locale
12-
from .math.point import Point
13-
from .matrices import Matrix2x3
14-
from .pixel_utils import get_pixel_encode_function, get_raw_mode
9+
from xcoder.bytestream import Reader, Writer
10+
from xcoder.console import Console
11+
from xcoder.localization import locale
12+
from xcoder.math.point import Point
13+
from xcoder.matrices import Matrix2x3
14+
from xcoder.pixel_utils import get_pixel_encode_function, get_raw_mode
1515

1616
CHUNK_SIZE = 32
1717

@@ -47,11 +47,11 @@ def join_image(
4747
raw_mode = get_raw_mode(pixel_type)
4848

4949
for chunk_index in range(chunk_count):
50-
chunk_x = chunk_index % chunk_count_x
51-
chunk_y = chunk_index // chunk_count_x
50+
chunk_x = (chunk_index % chunk_count_x) * CHUNK_SIZE
51+
chunk_y = (chunk_index // chunk_count_x) * CHUNK_SIZE
5252

53-
chunk_width = min(width - chunk_x * CHUNK_SIZE, CHUNK_SIZE)
54-
chunk_height = min(height - chunk_y * CHUNK_SIZE, CHUNK_SIZE)
53+
chunk_width = min(width - chunk_x, CHUNK_SIZE)
54+
chunk_height = min(height - chunk_y, CHUNK_SIZE)
5555

5656
sub_image = Image.frombuffer(
5757
mode,
@@ -63,7 +63,7 @@ def join_image(
6363
1,
6464
)
6565

66-
image.paste(sub_image, (chunk_x * CHUNK_SIZE, chunk_y * CHUNK_SIZE))
66+
image.paste(sub_image, (chunk_x, chunk_y))
6767

6868
Console.progress_bar(locale.join_pic, chunk_index, chunk_count)
6969

@@ -76,40 +76,33 @@ def _add_pixel(
7676
image[pixel_index % width, int(pixel_index / width)] = color
7777

7878

79-
def split_image(img: Image.Image) -> None:
80-
width, height = img.size
79+
def split_image(image: Image.Image) -> Image.Image:
80+
width, height = image.size
8181

82-
loaded_image = img.load()
83-
if loaded_image is None:
84-
raise Exception("loaded_image is None")
82+
chunk_count_x = math.ceil(width / CHUNK_SIZE)
83+
chunk_count_y = math.ceil(height / CHUNK_SIZE)
84+
chunk_count = chunk_count_x * chunk_count_y
8585

86-
loaded_clone = img.copy().load()
87-
if loaded_clone is None:
88-
raise Exception("loaded_clone is None")
86+
split_image_buffers = []
8987

90-
x_chunks_count = width // CHUNK_SIZE
91-
y_chunks_count = height // CHUNK_SIZE
88+
for chunk_index in range(chunk_count):
89+
chunk_x = (chunk_index % chunk_count_x) * CHUNK_SIZE
90+
chunk_y = (chunk_index // chunk_count_x) * CHUNK_SIZE
9291

93-
pixel_index = 0
92+
chunk_width = min(width - chunk_x, CHUNK_SIZE)
93+
chunk_height = min(height - chunk_y, CHUNK_SIZE)
9494

95-
for y_chunk in range(y_chunks_count + 1):
96-
for x_chunk in range(x_chunks_count + 1):
97-
for y in range(CHUNK_SIZE):
98-
pixel_y = (y_chunk * CHUNK_SIZE) + y
99-
if pixel_y >= height:
100-
break
95+
chunk = image.crop(
96+
(chunk_x, chunk_y, chunk_x + chunk_width, chunk_y + chunk_height)
97+
)
10198

102-
for x in range(CHUNK_SIZE):
103-
pixel_x = (x_chunk * CHUNK_SIZE) + x
104-
if pixel_x >= width:
105-
break
99+
split_image_buffers.append(chunk.tobytes("raw"))
106100

107-
_add_pixel(
108-
loaded_image, pixel_index, width, loaded_clone[pixel_x, pixel_y]
109-
)
110-
pixel_index += 1
101+
Console.progress_bar(locale.split_pic, chunk_index, chunk_count)
111102

112-
Console.progress_bar(locale.split_pic, y_chunk, y_chunks_count + 1)
103+
return Image.frombuffer(
104+
image.mode, image.size, b"".join(split_image_buffers), "raw"
105+
)
113106

114107

115108
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:
136129

137130

138131
def save_texture(writer: Writer, image: Image.Image, pixel_type: int) -> None:
132+
raw_mode = get_raw_mode(pixel_type)
139133
encode_pixel = get_pixel_encode_function(pixel_type)
140-
if encode_pixel is None:
141-
raise Exception(locale.unknown_pixel_type % pixel_type)
142134

143135
width, height = image.size
144136

145137
pixels = image.getdata()
146-
for y in range(height):
147-
for x in range(width):
148-
# noinspection PyTypeChecker
149-
writer.write(encode_pixel(pixels[y * width + x]))
150138

151-
Console.progress_bar(locale.writing_pic, y, height)
139+
# Some packers for raw_encoder are absent
140+
# https://github.com/python-pillow/Pillow/blob/58e48745cc7b6c6f7dd26a50fe68d1a82ea51562/src/encode.c#L337
141+
# https://github.com/python-pillow/Pillow/blob/main/src/libImaging/Pack.c#L668
142+
if raw_mode != image.mode and encode_pixel is not None:
143+
for y in range(height):
144+
for x in range(width):
145+
# noinspection PyTypeChecker
146+
writer.write(encode_pixel(pixels[y * width + x]))
147+
148+
Console.progress_bar(locale.writing_pic, y, height)
149+
150+
return
151+
152+
writer.write(image.tobytes("raw", raw_mode, 0, 1))
153+
Console.progress_bar(locale.writing_pic, height - 1, height)
152154

153155

154156
def transform_image(

xcoder/pixel_utils.py

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -57,25 +57,13 @@ def _write_rgb565(pixel: PixelChannels) -> bytes:
5757
return struct.pack("<H", b >> 3 | g >> 2 << 5 | r >> 3 << 11)
5858

5959

60-
def _write_luminance8_alpha8(pixel: PixelChannels) -> bytes:
61-
return struct.pack("2B", *pixel[::-1])
62-
63-
64-
def _write_luminance8(pixel: PixelChannels) -> bytes:
65-
return struct.pack("B", pixel)
66-
67-
6860
_encode_functions: dict[int, EncodeFunction] = {
69-
0: _write_rgba8,
70-
1: _write_rgba8,
7161
2: _write_rgba4,
7262
3: _write_rgb5a1,
7363
4: _write_rgb565,
74-
6: _write_luminance8_alpha8,
75-
10: _write_luminance8,
7664
}
7765

78-
# here is a problem with this names https://github.com/python-pillow/Pillow/pull/8158
66+
# here is a problem with these names https://github.com/python-pillow/Pillow/pull/8158
7967
_raw_modes: dict[int, RawMode] = {
8068
0: "RGBA",
8169
1: "RGBA",

0 commit comments

Comments
 (0)