Metadata-Version: 2.1
Name: alktx2
Version: 0.1.3
Summary: High-level KTX2 <-> image (png/jpg/webp) conversion powered by Basis Universal (basisu).
Author-Email: "Lun.A" <517308447@qq.com>
Maintainer-Email: "Lun.A" <517308447@qq.com>
Requires-Python: >=3.11
Description-Content-Type: text/markdown

## alktx2

`alktx2` 是一个**高集成度**的图片 ↔ KTX2 转换库：用户 `pip install` 后即可通过少量函数完成：

- **png/jpg/webp/tga/tiff → ktx2**（选择 Basis Universal 的编码算法，并暴露关键调参）
- **ktx2 → png/jpg/webp/tga/tiff**（把 KTX2 解码为 RGBA8，再编码成常见图片格式）

项目目标是：**接口极简、参数可控、性能足够好、并尽量保留 basisu 的能力（在 Python 侧以更友好的方式暴露）**。

### 支持的图片格式（与 KTX2 的互转）

| 方向 | 格式 | 扩展名 / MIME 要点 | 实现说明 |
|------|------|-------------------|----------|
| 图片 → KTX2 | PNG | `.png` / `image/png` | `stb_image` 解码为 RGBA8 |
| 图片 → KTX2 | JPEG | `.jpg` `.jpeg` / `image/jpeg` | `stb_image` |
| 图片 → KTX2 | WebP | `.webp` / `image/webp` | `libwebp` |
| 图片 → KTX2 | TGA | `.tga` / `image/x-tga` | `stb_image` |
| 图片 → KTX2 | TIFF | `.tif` `.tiff` / `image/tiff` | `libtiff`（常见压缩与 RGBA 接口可读；极冷门 photometric 可能失败） |
| KTX2 → 图片 | PNG | `format="png"` | `stb_image_write`，未压缩 |
| KTX2 → 图片 | JPEG | `format="jpg"` | `stb_image_write` |
| KTX2 → 图片 | WebP | `format="webp"` | `libwebp` |
| KTX2 → 图片 | TGA | `format="tga"` | `stb_image_write`，**未使用 RLE** 的 TGA |
| KTX2 → 图片 | TIFF | `format="tif"` 或 `format="tiff"` | `libtiff` 写出 **未压缩 RGBA** TIFF |

批处理写出文件时，`format="tiff"` 与 `format="tif"` 均使用 `.tif` 后缀。





## 快速上手

### 图片文件 ↔ KTX2 文件

```python
import alktx2

# png -> ktx2（更偏分发/体积）
alktx2.encode_image_to_ktx2(
    "a.png",
    "a.ktx2",
    codec="etc1s",
    quality=50,
    effort=3,
    srgb=True,
)

# ktx2 -> webp（方便快速预览）
alktx2.decode_ktx2_to_image(
    "a.ktx2",
    "a.webp",
    format="webp",
    quality=85,
    method=4,
)
```



### bytes ↔ bytes（适合服务端/管线）

```python
import alktx2

with open("a.webp", "rb") as f:
    img = f.read()

ktx2 = alktx2.encode_bytes_to_ktx2(
    img,
    mime="image/webp",
    codec="uastc",
    quality=80,
    effort=4,
    zstd_supercompression_level=6,
)

png_bytes, mime = alktx2.decode_ktx2_to_bytes(ktx2, format="png")
assert mime == "image/png"
```

## 便捷：mime 简写

`encode_bytes_to_ktx2(..., mime=...)` 支持两种写法：

- 标准 MIME：`image/png`、`image/jpeg`、`image/webp`
- 常见简写：`png`、`jpg`、`jpeg`、`webp`、`tga` 等（忽略大小写）

示例：

```python
ktx2 = alktx2.encode_bytes_to_ktx2(img_bytes, mime="jpg")
```

TIFF 输入依赖 vendored **libtiff** 与 **zlib**（见 `build.md` / `THIRD_PARTY_NOTICES.md`）。

## 批处理：目录 ↔ 目录（默认吃满 CPU）

当你需要一次性处理大量图片/ktx2 时，建议使用目录接口：

- `encode_images_dir_to_ktx2_dir()`：图片目录 → ktx2 目录
- `decode_ktx2_dir_to_images_dir()`：ktx2 目录 → 图片目录

它们支持：
- **recursive**：是否递归子目录
- **suffixes**：后缀过滤（忽略大小写，可写 `png` 或 `.png`）
- **prefix**：文件名前缀过滤（忽略大小写）
- **workers**：并发数（默认 CPU 核心数）

示例：

```python
import alktx2

# 批量图片 -> ktx2（保持目录结构）
alktx2.encode_images_dir_to_ktx2_dir(
    "E:/textures",
    "E:/textures_ktx2",
    recursive=True,
    suffixes=["png", "jpg", "webp", "tga"],
    codec="etc1s",
    quality=50,
    effort=3,
    # 批处理建议 threads=1，通过 workers 吃满 CPU，避免过度抢占
    threads=1,
)

# 批量 ktx2 -> png
alktx2.decode_ktx2_dir_to_images_dir(
    "E:/textures_ktx2",
    "E:/textures_png_preview",
    recursive=True,
    suffixes=[".ktx2"],
    format="png",
    level=0,
)
```

## 并发建议（重要）

`alktx2` 在**单次编码**时就可以通过 `threads=0` 自动使用多核（默认即为 0，会尽量吃满 CPU）。
因此通常不需要、也不建议在 Python 层再叠加并发（否则很容易出现“过度抢占”导致更慢，甚至内存暴涨）。

- **不建议使用 `multiprocessing` / 进程池**：每个子进程内部都会再开多线程，整体 CPU/内存会被迅速打满。\n
  如果你一定要做并发，优先使用本库提供的目录批处理接口（`workers` 控制并发）。\n
- **不建议叠加 Python 3.14 的 free-threading 并发**：本库的热点在 C++ 编码/解码，多线程在底层已经做了；\n
  Python 层再并发通常只会更混乱（尤其是同时 `workers` + `threads=0` 的情况下）。



## 参数总览（重点）

`alktx2` 目前对外暴露 5 个高集成度接口：

- `encode_image_to_ktx2()` / `encode_bytes_to_ktx2()`\n
  - 核心是 **BasisU 编码参数**。\n
- `decode_ktx2_to_image()` / `decode_ktx2_to_bytes()`\n
  - 核心是 **输出图片编码参数**（webp/jpg 质量等）。\n
- `inspect_ktx2()`\n
  - 不解码像素，只读 KTX2 元信息（codec/块尺寸/色彩传递函数等）。\n

下面按“你最常用的图片 ↔ KTX2”场景解释关键参数（更完整的接口说明请以 `src/alktx2/__init__.pyi` 为准）。



### 编码：图片 → KTX2

#### 1) 通用参数（推荐优先掌握）
- **codec**：\n
  - `etc1s`：更小的体积（常用于下载分发），质量一般\n
  - `uastc`：更高质量（常用于近似无明显瑕疵），文件更大\n
  - `astc_ldr` / `xuastc_ldr`：ASTC/XUASTC LDR（当前默认块大小 6x6）
- **quality**：1-100（质量/体积权衡）
- **effort**：0-10（速度/最高可达质量权衡）
- **srgb / linear**：互斥。\n
  - 色彩贴图（albedo/baseColor/UI）：一般 `srgb=True`\n
  - 法线/金属度/粗糙度/高度等数据贴图：一般 `linear=True`
- **threads**：0 自动；>0 指定线程池总线程数（更快但更吃 CPU）

#### 2) KTX2（supercompression）
- **zstd_supercompression_level**：对支持的模式启用 KTX2 的 Zstd supercompression。\n
  - 常用于 `uastc`：更利于分发（更小），但编码更慢。\n
  - `None` 表示使用库默认。

#### 3) mipmap（当 mipmaps=True 时才生效）
- **mipmaps**：是否自动生成 mipmap（强烈建议用于 3D 场景）
- **mip_wrap**：生成 mip 时使用 wrap（True）或 clamp（False）
- **mip_filter**：滤波器名称（空串=使用 basisu 默认）
- **mip_scale / mip_smallest_dimension**：控制 mip 生成策略

#### 4) UASTC（LDR 4x4）RDO（更小但更有损）
- **uastc_rdo_lambda**：>0 开启 RDO；越大通常文件更小但质量下降。\n
  - 经验值：`0.5 ~ 1.5` 常作为起点。\n
- **uastc_rdo_dict_size**：RDO 字典大小，None=默认

#### 5) XUASTC profile（更偏“可转码速度 vs 压缩率”）
- **xuastc_syntax**：`\"\" | \"zstd\" | \"hybrid\" | \"arith\"`\n
  - `zstd`：转码更快，压缩率略差\n
  - `arith`：压缩率更好，转码更慢\n
  - `hybrid`：折中\n
- **xuastc_disable_subsets / xuastc_disable_dual_plane**：偏向“转码到 BC7 更快/更稳定”的开关（可能牺牲质量）

#### 6) Alpha/内容提示
- **check_for_alpha**：是否检测输入 alpha（默认 True）
- **force_alpha**：强制输出 alpha（默认 False）
- **renormalize**：法线贴图 renormalize（默认 False）
- **y_flip**：编码前沿 Y 翻转（默认 False）

### 解码：KTX2 → 图片（png/jpg/webp/tga/tiff）

- **format**：`png` / `jpg` / `webp` / `tga` / `tif` / `tiff`
- **quality**：\n
  - `jpg`：1-100\n
  - `webp`：0-100（lossy）\n
- **lossless / near_lossless / method**：仅对 `webp` 输出生效（更完整说明见 `.pyi`）



## 原理（实现链路）

### 编码：图片 → KTX2（BasisU）
1. **图片解码**：\n
   - png/jpg/tga 等：`stb_image` 解码到 RGBA8\n
   - webp：`libwebp` 解码到 RGBA8\n
   - tiff：`libtiff` 经 `TIFFReadRGBAImageOriented` 转为 RGBA8\n
2. **BasisU 编码**：把 RGBA8 交给 `basisu::basis_compressor`，通过 `basisu::basis_compressor_params` 进行参数映射，产出 `.ktx2`。\n
3. **返回/写盘**：返回 bytes 或写出到文件。

### 解码：KTX2 → 图片
1. **KTX2 解析与转码**：使用 `basist::ktx2_transcoder`，将 KTX2 解码/转码为 `RGBA32`（即 RGBA8 像素）。\n
2. **图片编码**：\n
   - png/jpg/tga：`stb_image_write` 编码\n
   - webp：`libwebp` 编码\n
   - tiff：`libtiff` 写出未压缩 RGBA\n

## 已知限制（当前版本）
- **KTX2 解码**：默认解码 **level=0, layer=0, face=0**，但现在你可以在 `decode_ktx2_to_*()` 中显式指定：\n
  - `level`：mipmap level（0 为最大分辨率）\n
  - `layer`：texture array / video frame 的层索引（如果 `inspect_ktx2()` 返回 `layers=0`，则有效层数视为 1）\n
  - `face`：cubemap 面（2D=0；cubemap=0..5）\n
  - 这使得后续扩展到批量导出/更多结构变得更自然。\n
- **HDR/特殊 DFD**：当前以 LDR/常见用途为主，后续会逐步补齐 HDR/更多 DFD 解释与更强的格式兼容性提示。

## 发布到 PyPI（多版本 wheel）

本地一键构建 Windows / Linux manylinux（cp311–cp314）并可选上传：见 **[scripts/README.md](scripts/README.md)**（命令示例：`.\scripts\build_local_wheels.ps1 -UploadToPyPI`）。

## inspect_ktx2() 字段说明（简要）

`inspect_ktx2()` 返回的字典包含：

- **基础结构**：`width/height/levels/layers/faces`
- **alpha 与 transfer function**：`has_alpha/is_srgb`
- **BasisU codec**：`basis_tex_format`（枚举值）与 `basis_tex_format_name`（可读字符串）
- **类型判断**：`is_hdr/is_etc1s/is_uastc/is_astc_ldr/is_xuastc_ldr`
- **块尺寸**：`block_width/block_height`（例如 ETC1S/UASTC 常见为 4x4）
- **DFD（Data Format Descriptor）摘要**：`dfd_color_model/dfd_transfer_func/dfd_channel_id0/dfd_channel_id1`\n
  这些字段用于快速判断数据语义（例如是否 sRGB、通道映射等）。更深入解释后续会补充。
