add twiddle
This commit is contained in:
parent
5097e0e5ac
commit
5f4b0070a6
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
__pycache__/
|
@ -2,6 +2,7 @@ import struct
|
||||
import sys
|
||||
|
||||
from PIL import Image
|
||||
from twiddle import texture as twiddle_texture
|
||||
|
||||
class color_format:
|
||||
def gbgr1555(r, g, b, a): # nintendo ds
|
||||
@ -29,7 +30,7 @@ class color_format:
|
||||
r5 = (r >> 3) & 31
|
||||
g6 = (g >> 2) & 63
|
||||
b5 = (b >> 3) & 31
|
||||
return (r5 << 11) | (g5 << 5) | (b5 << 0)
|
||||
return (r5 << 11) | (g6 << 5) | (b5 << 0)
|
||||
|
||||
def axxx4444(r, g, b, a):
|
||||
a4 = (a >> 4) & 15
|
||||
@ -44,12 +45,12 @@ class color_format:
|
||||
("axxx4444", color_format.axxx4444),
|
||||
])[s]
|
||||
|
||||
def convert_colors(f, convert, colors):
|
||||
def convert_colors(convert, colors):
|
||||
for color in colors:
|
||||
value = convert(*color)
|
||||
f.write(struct.pack("<H", value))
|
||||
yield value
|
||||
|
||||
def convert_indices(f, palette, pixels):
|
||||
def convert_indices(palette, pixels):
|
||||
if len(palette) <= 4:
|
||||
for i in range(len(pixels) // 4):
|
||||
a = pixels[i * 4 + 0]
|
||||
@ -73,22 +74,47 @@ def convert_indices(f, palette, pixels):
|
||||
else:
|
||||
assert False, len(palette)
|
||||
|
||||
def pack_colors(f, colors):
|
||||
for value in colors:
|
||||
f.write(struct.pack("<H", value))
|
||||
|
||||
def pack_indices(f, indices):
|
||||
for value in indices:
|
||||
f.write(struct.pack("<B", value))
|
||||
|
||||
if __name__ == "__main__":
|
||||
in_file = sys.argv[1]
|
||||
format = sys.argv[2]
|
||||
out_file = sys.argv[3]
|
||||
assert sys.argv[3] in {"twiddled", "non_twiddled"}
|
||||
is_twiddled = sys.argv[3] == "twiddled"
|
||||
out_file = sys.argv[4]
|
||||
|
||||
convert = color_format.from_string(format)
|
||||
|
||||
with Image.open(in_file) as im:
|
||||
width, height = im.size
|
||||
if not im.palette:
|
||||
pixels = list(im.convert("RGBA").getdata())
|
||||
colors = list(convert_colors(convert, pixels))
|
||||
if is_twiddled:
|
||||
new_colors = [0] * len(colors)
|
||||
twiddle_texture(new_colors, colors, width, height)
|
||||
colors = new_colors
|
||||
with open(out_file, 'wb') as f:
|
||||
convert_colors(f, convert, pixels)
|
||||
pack_colors(f, colors)
|
||||
else:
|
||||
pixels = list(im.convert("P").getdata())
|
||||
palette = list(im.palette.colors)
|
||||
with open(out_file, 'wb') as f:
|
||||
convert_indices(f, palette, pixels)
|
||||
indices = list(convert_indices(palette, pixels))
|
||||
colors = list(convert_colors(convert, [(*c, 255) for c in palette]))
|
||||
|
||||
if twiddle:
|
||||
new_indices = [0] * len(indices)
|
||||
twiddle_texture(new_indices, indices, width, height)
|
||||
indices = new_indices
|
||||
|
||||
with open(out_file + '.pal', 'wb') as f:
|
||||
convert_colors(f, convert, [(*c, 255) for c in palette])
|
||||
pack_colors(f, colors)
|
||||
|
||||
with open(out_file, 'wb') as f:
|
||||
pack_indices(f, indices)
|
||||
|
@ -8,17 +8,19 @@ from PIL import Image
|
||||
|
||||
from parse_material import parse_mtl_file
|
||||
|
||||
material_filenames = sys.argv[1:]
|
||||
|
||||
def render_material_enum(newmtl_mapkd):
|
||||
def render_material_enum(prefix, newmtl_mapkd):
|
||||
yield f"enum material {{"
|
||||
for newmtl, mapkd in newmtl_mapkd:
|
||||
yield f"{newmtl.name},";
|
||||
yield f"{prefix}_{newmtl.name},";
|
||||
yield "};"
|
||||
|
||||
def render_pixel_descriptor(offset, mapkd, dimensions):
|
||||
def transform_filename(prefix, name):
|
||||
name = name.replace("/", "_")
|
||||
return f"model_{prefix}_{name}"
|
||||
|
||||
def render_pixel_descriptor(prefix, offset, mapkd, dimensions):
|
||||
name, _ext = mapkd.name.rsplit('.', maxsplit=1)
|
||||
pixel_name = f"{name}_data"
|
||||
pixel_name = f"{transform_filename(prefix, name)}_data"
|
||||
width, height = dimensions
|
||||
yield ".pixel = {"
|
||||
yield f".start = (uint8_t *)&_binary_{pixel_name}_start,"
|
||||
@ -54,12 +56,10 @@ def round_up_colors(name, colors):
|
||||
else:
|
||||
assert False, (name, colors)
|
||||
|
||||
def image_metadata(mapkd):
|
||||
def image(mapkd):
|
||||
path = texture_path(mapkd.name)
|
||||
with Image.open(path) as im:
|
||||
dimensions = im.size
|
||||
colors = len(im.palette.colors)
|
||||
return dimensions, colors
|
||||
im = Image.open(path)
|
||||
return im
|
||||
|
||||
def round_up_n(x, multiple):
|
||||
return ((x + multiple - 1) // multiple) * multiple
|
||||
@ -68,27 +68,30 @@ def bytes_per_pixel(palette_size):
|
||||
bits_per_pixel = int(log(palette_size)/log(2))
|
||||
return bits_per_pixel / 8
|
||||
|
||||
def render_material(offset, mapkd):
|
||||
dimensions, colors = image_metadata(mapkd)
|
||||
palette_size = round_up_colors(mapkd.name, colors)
|
||||
def render_material(prefix, offset, mapkd):
|
||||
im = image(mapkd)
|
||||
dimensions = im.size
|
||||
#colors = len(im.palette.colors)
|
||||
|
||||
#palette_size = round_up_colors(mapkd.name, colors)
|
||||
|
||||
# pixel descriptor
|
||||
yield from render_pixel_descriptor(offset, mapkd, dimensions)
|
||||
pixel_size = bytes_per_pixel(palette_size) * dimensions[0] * dimensions[1]
|
||||
#pixel_size = 2 * dimensions[0] * dimensions[1]
|
||||
yield from render_pixel_descriptor(prefix, offset, mapkd, dimensions)
|
||||
#pixel_size = bytes_per_pixel(palette_size) * dimensions[0] * dimensions[1]
|
||||
pixel_size = 2 * dimensions[0] * dimensions[1]
|
||||
assert int(pixel_size) == pixel_size
|
||||
offset.pixel += round_up_n(int(pixel_size), 8)
|
||||
|
||||
# palette descriptor
|
||||
yield from render_palette_descriptor(offset, mapkd, palette_size)
|
||||
offset.palette += round_up_n(colors * 2, 16)
|
||||
#yield from render_palette_descriptor(offset, mapkd, palette_size)
|
||||
#offset.palette += round_up_n(colors * 2, 16)
|
||||
|
||||
def render_materials(newmtl_mapkd):
|
||||
yield "struct material_descriptor material[] = {"
|
||||
def render_materials(prefix, newmtl_mapkd):
|
||||
yield f"const struct material_descriptor {prefix}_material[] = {{"
|
||||
offset = Offset(0, 0)
|
||||
for newmtl, mapkd in newmtl_mapkd:
|
||||
yield f"[{newmtl.name}] = {{"
|
||||
yield from render_material(offset, mapkd)
|
||||
yield f"[{prefix}_{newmtl.name}] = {{"
|
||||
yield from render_material(prefix, offset, mapkd)
|
||||
yield "},"
|
||||
yield "};"
|
||||
|
||||
@ -101,7 +104,8 @@ def render_header():
|
||||
yield ""
|
||||
|
||||
if __name__ == "__main__":
|
||||
material_filenames = sys.argv[1:]
|
||||
prefix = sys.argv[1]
|
||||
material_filenames = sys.argv[2:]
|
||||
assert material_filenames
|
||||
newmtl_mapkd = []
|
||||
for material_filename in material_filenames:
|
||||
@ -114,6 +118,6 @@ if __name__ == "__main__":
|
||||
|
||||
render, out = renderer()
|
||||
render(render_header())
|
||||
render(render_material_enum(newmtl_mapkd))
|
||||
render(render_materials(newmtl_mapkd))
|
||||
render(render_material_enum(prefix, newmtl_mapkd))
|
||||
render(render_materials(prefix, newmtl_mapkd))
|
||||
sys.stdout.write(out.getvalue())
|
||||
|
43
twiddle.py
Normal file
43
twiddle.py
Normal file
@ -0,0 +1,43 @@
|
||||
def log2(n):
|
||||
return {
|
||||
8: 3,
|
||||
16: 4,
|
||||
32: 5,
|
||||
64: 6,
|
||||
128: 7,
|
||||
256: 8,
|
||||
512: 9,
|
||||
1024: 10,
|
||||
}[n]
|
||||
|
||||
def from_xy(x, y, width, height):
|
||||
# maximum texture size : 1024x1024
|
||||
# maximum 1-dimensional index: 0xfffff
|
||||
# bits : 19-0
|
||||
|
||||
# y bits: 0, 2, 4, 6, 8, 10, 12, 14, 16, 18
|
||||
# x bits: 1, 3, 5, 7, 9, 11, 13, 15, 17, 19
|
||||
|
||||
width_max = log2(width)
|
||||
height_max = log2(height)
|
||||
|
||||
twiddle_ix = 0
|
||||
for i in range(20 // 2):
|
||||
if (i < width_max and i < height_max):
|
||||
twiddle_ix |= ((y >> i) & 1) << (i * 2 + 0)
|
||||
twiddle_ix |= ((x >> i) & 1) << (i * 2 + 1)
|
||||
elif (i < width_max):
|
||||
twiddle_ix |= ((x >> i) & 1) << (i + height_max)
|
||||
elif (i < height_max):
|
||||
twiddle_ix |= ((y >> i) & 1) << (i + width_max)
|
||||
else:
|
||||
break
|
||||
|
||||
return twiddle_ix
|
||||
|
||||
def texture(dst, src, width, height):
|
||||
for y in range(height):
|
||||
for x in range(width):
|
||||
twiddle_ix = from_xy(x, y, width, height)
|
||||
value = src[y * width + x]
|
||||
dst[twiddle_ix] = value
|
Loading…
x
Reference in New Issue
Block a user