mirror of
https://github.com/BinomialLLC/basis_universal.git
synced 2026-06-08 00:23:52 +00:00
84 lines
2.7 KiB
Python
84 lines
2.7 KiB
Python
# astc_writer.py
|
|
#
|
|
# Minimal ASTC writer that mirrors the C/C++ write_astc_file() logic from example_capi.c.
|
|
# Writes a valid single-slice 2D ASTC texture file (no array slices, no 3D, no mips).
|
|
#
|
|
# Usage:
|
|
# from astc_writer import write_astc_file
|
|
# write_astc_file("output.astc", blocks, block_width, block_height, width, height)
|
|
#
|
|
# "blocks" must be a bytes-like object containing the full ASTC block data
|
|
# using 16 bytes per block (standard ASTC block size).
|
|
|
|
|
|
def write_astc_file(
|
|
filename: str,
|
|
blocks: bytes,
|
|
block_width: int,
|
|
block_height: int,
|
|
width: int,
|
|
height: int
|
|
) -> None:
|
|
"""
|
|
Write an ASTC file to disk.
|
|
|
|
Parameters:
|
|
filename : Output filename ("something.astc")
|
|
blocks : Bytes-like object containing ASTC blocks (16 bytes per block)
|
|
block_width : ASTC block width (e.g. 4-12)
|
|
block_height : ASTC block height (e.g. 4-12)
|
|
width : Original image width in pixels
|
|
height : Original image height in pixels
|
|
|
|
Notes:
|
|
- ASTC files use 2D blocks; depth is always 1.
|
|
- Block layout goes row-major: (num_blocks_y num_blocks_x) blocks.
|
|
- No mipmaps are stored in this format.
|
|
"""
|
|
|
|
# Validate block dimensions
|
|
if block_width < 4 or block_width > 12:
|
|
raise ValueError(f"ASTC block_width {block_width} out of range (412)")
|
|
if block_height < 4 or block_height > 12:
|
|
raise ValueError(f"ASTC block_height {block_height} out of range (412)")
|
|
|
|
# Compute block grid
|
|
num_blocks_x = (width + block_width - 1) // block_width
|
|
num_blocks_y = (height + block_height - 1) // block_height
|
|
total_blocks = num_blocks_x * num_blocks_y
|
|
expected_size = total_blocks * 16 # 16 bytes per ASTC block (always)
|
|
|
|
if len(blocks) != expected_size:
|
|
raise ValueError(
|
|
f"ASTC block buffer incorrect size: expected {expected_size}, got {len(blocks)}"
|
|
)
|
|
|
|
# Write file
|
|
with open(filename, "wb") as f:
|
|
# ASTC magic number (0x13AB A15C)
|
|
f.write(bytes([0x13, 0xAB, 0xA1, 0x5C]))
|
|
|
|
# Block dims: x, y, z (z=1)
|
|
f.write(bytes([
|
|
block_width & 0xFF,
|
|
block_height & 0xFF,
|
|
1
|
|
]))
|
|
|
|
# ASTC stores width/height/depth as 24-bit LE
|
|
def write_24bit_le(v: int):
|
|
f.write(bytes([
|
|
v & 0xFF,
|
|
(v >> 8) & 0xFF,
|
|
(v >> 16) & 0xFF
|
|
]))
|
|
|
|
write_24bit_le(width)
|
|
write_24bit_le(height)
|
|
write_24bit_le(1) # depth
|
|
|
|
# Write actual block payload
|
|
f.write(blocks)
|
|
|
|
print(f"[ASTC Writer] Wrote: {filename} ({width}x{height}, {block_width}x{block_height} blocks)")
|