File: astc_writer.py

package info (click to toggle)
basis-universal 2.0.2-3
  • links: PTS
  • area: main
  • in suites: forky, sid
  • size: 216,436 kB
  • sloc: cpp: 163,224; ansic: 51,368; python: 2,824; javascript: 2,637; lisp: 1,026; sh: 161; makefile: 17
file content (83 lines) | stat: -rw-r--r-- 2,749 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# 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)")