66 lines
1.9 KiB
Python
66 lines
1.9 KiB
Python
"""
|
||
将 PNG 图片转换为 C 头文件(RGBA5551 / uint16_t 像素数组)。
|
||
|
||
用法:
|
||
python tools/png_to_header.py input.png output.h [var_name]
|
||
|
||
像素格式: RGBA5551(5-bit R, 5-bit G, 5-bit B, 1-bit A)
|
||
运行时 sprite 主路径只保留 1-bit 透明:A=0 跳过,A=1 覆写。
|
||
"""
|
||
|
||
import sys
|
||
import os
|
||
|
||
from PIL import Image
|
||
|
||
|
||
def convert(input_path: str, output_path: str, var_name: str):
|
||
img = Image.open(input_path).convert("RGBA")
|
||
w, h = img.size
|
||
pixels = list(img.getdata()) if not hasattr(img, "get_flattened_data") else list(img.get_flattened_data())
|
||
|
||
packed = []
|
||
for r, g, b, a in pixels:
|
||
packed.append(
|
||
((r >> 3) << 11)
|
||
| ((g >> 3) << 6)
|
||
| ((b >> 3) << 1)
|
||
| (1 if a else 0)
|
||
)
|
||
|
||
with open(output_path, "w", encoding="utf-8") as f:
|
||
f.write("// Auto-generated by tools/png_to_header.py\n")
|
||
f.write(f"#pragma once\n#include <cstdint>\n\n")
|
||
f.write(f"static const int32_t {var_name}_width = {w};\n")
|
||
f.write(f"static const int32_t {var_name}_height = {h};\n\n")
|
||
f.write(f"static const uint16_t {var_name}_pixels[] = {{\n")
|
||
|
||
for i in range(0, len(packed), 16):
|
||
chunk = packed[i : i + 16]
|
||
line = ", ".join(f"0x{p:04X}" for p in chunk)
|
||
f.write(f" {line},\n")
|
||
|
||
f.write("};\n")
|
||
|
||
|
||
def main():
|
||
if len(sys.argv) < 3:
|
||
print(f"用法: {sys.argv[0]} input.png output.h [var_name]")
|
||
sys.exit(1)
|
||
|
||
input_path = sys.argv[1]
|
||
output_path = sys.argv[2]
|
||
|
||
if len(sys.argv) >= 4:
|
||
var_name = sys.argv[3]
|
||
else:
|
||
# 从文件名生成变量名: player_idle.png -> player_idle
|
||
var_name = os.path.splitext(os.path.basename(input_path))[0]
|
||
|
||
convert(input_path, output_path, var_name)
|
||
print(f"已生成: {output_path} (var: {var_name}, 像素数: {var_name}_width * {var_name}_height)")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|