B67687/Ithmb-Codec
GitHub: B67687/Ithmb-Codec
该项目是一个基于 Rust 开发的 Apple .ithmb 缩略图缓存文件编解码器,解决了在非苹果环境下读取和转换早期 iPod/iPhone 专有图像格式的问题。
Stars: 0 | Forks: 0
一个纯 Rust 编解码器库、CLI 工具和 ImageGlass v10 插件,用于解码和编码 Apple `.ithmb` 缩略图缓存文件 —— 这是 iPod Classic/Nano/Photo/Video、iPhone 2G 和 iPod Touch 用于存储照片和专辑封面缩略图的格式。
**核心特性**
- 54 个内置配置文件(+ 1 个推测性的已禁用配置),涵盖已知的 iPod/iPhone 格式
- 8 个解码器(RGB565、RGB555、ReorderedRGB555、UYVY、YCbCr420、CLCL、CL、JPEG)
- 7 个合成编码器,适用于所有原始格式
- 经过往返验证的测试(486+ 个通过)
- PhotoDB/ArtworkDB 读取、写入和完整性检查
- 多帧 F 前缀原始文件支持
- 用于 iPhone 兼容性的 BGR15 通道交换
- 通过纯 Rust JPEG 解码器进行 JPEG 嵌入式 T 前缀解码
- 跨平台(Linux x64/ARM64、macOS x64/ARM64、Windows x64)
- C ABI 库,可 FFI 集成到现有应用程序中
- 用于解码、检查和帧提取的 CLI 工具
- YUV 转换路径的全面 SIMD 加速(SSE2+AVX2+NEON 运行时分发)
**T 前缀** — 包含嵌入的 JPEG。 ✅ 完全支持(已在 1,183 个真实文件上验证)。
**F 前缀**(例如 `F1019_1.ithmb`)— 原始未压缩缩略图(RGB565、RGB555、UYVY、YCbCr420、CLCL nibble-chroma)。 ✅ 与 iOpenPod 经验验证的集合(跨越多个 iPod 型号的 50+ 个配置文件)进行了交叉比对,并在真实的 iPod Classic 6G 样本(F1061/F1055/F1060)上得到确认。
🎖️ 特别感谢 Savi 和 iOpenPod 社区
感谢他们提供硬件验证 —— 购买多个 iPod 型号并跨固件版本测试配置文件。配置文件的调整融合了来自 iOpenPod 社区的反馈。
|
## 目录
- [工作原理](#how-it-works)
- [致谢](#acknowledgments)
- [安装](#install)
- [从源码构建](#build-from-source)
- [测试与验证](#testing--validation)
- [架构](#architecture)
- [CLI 工具](#cli-tool)
- [C ABI](#c-abi)
- [配置参考](#profile-reference)
- [限制](#limitations)
- [故障排除](#troubleshooting)
- [开发](#development)
- [对生态系统的贡献](#contributions-to-the-ecosystem)
- [更新日志](#changelog)
- [许可证](#license)
## 工作原理
1. **Peek 读取** — 将整个文件读入内存(峰值内存主要由解码后的位图占据,对于 iPhone 照片通常为几 MB)。32 MB 的大小限制可防止因异常输入导致 OOM。
2. **JPEG 扫描** — 检查在 512 字节内是否出现 JPEG SOI 标记(`FF D8`),随后跟随 JFIF 或 Exif。如果匹配,则提取 JPEG payload(SOI→EOI),通过 `jpeg-decoder` 解码,并通过配置系统公开其 EXIF 方向标签(0x0112)。
3. **原始回退** — 如果未找到 JPEG,解码器会将前 4 个字节(大端序前缀)与 54 个已知配置进行匹配,并运行相应的原始解码器(RGB565、RGB555、Reordered RGB555、UYVY、YCbCr420、YUV422 interlaced、CLCL nibble-chroma 或 CL per-pixel chroma)以生成 BGRA 输出。如果前缀与任何已知配置均不匹配,则在拒绝该文件之前,会扫描其内部嵌入的 JPEG 标记(字节级 carving)。可以通过 `profiles.json` 激活其他解码器变体:YCbCr 4:2:0 的色度平面交换、per-pixel vs shared nibble chroma、字节序切换、隔行场序、填充帧处理以及 BGR15 格式的通道交换。
4. **PhotoDB/ArtworkDB** — Apple 的 iPod 缩略图数据库(PhotoDB、ArtworkDB)使用基于二进制块的格式(MHFD→MHSD→MHNI 条目)。当文件以 `mhfd` 开头时,编解码器会解析块树,提取单个缩略图(内联像素数据或外部 `.ithmb` 文件引用),并通过匹配其格式 ID 的原始解码器对每个缩略图进行解码。支持读取、写入和完整性检查。
### 文件大小限制
## 安装
### 库
将 `ithmb-core` crate 添加到您的 `Cargo.toml` 中:
```
[dependencies]
ithmb-core = { git = "https://github.com/B67687/ithmb-codec" }
```
或者直接使用 CLI 二进制文件(参见[发布版本](https://github.com/B67687/ithmb-codec/releases))。
### CLI 工具
```
cargo install --git https://github.com/B67687/ithmb-codec ithmb-cli
```
这将安装 `ithmb` 二进制文件。
## 从源码构建
### 环境要求
- [Rust](https://rust-lang.org) 1.85 或更高版本(edition 2024)
- C 编译器工具链(用于原生代码链接)
### 构建
```
# Clone 仓库
git clone https://github.com/B67687/ithmb-codec.git
cd ithmb-codec
# 以 release 模式构建所有内容
cargo build --release
```
该工作区会生成五个产物:
| Crate | 二进制/库文件 | 位置 |
|-------|---------------|----------|
| `ithmb-core` | `libithmb_core.rlib`(静态库) | `target/release/` |
| `ithmb-cli` | `ithmb`(CLI 二进制文件) | `target/release/` |
| `ithmb-core-cabi` | `libithmb_core_cabi.so` / `.dylib` / `.dll`(C ABI 动态库) | `target/release/` |
| `ithmb-python` | `libithmb_python.so` (PyO3 abi3-py312) | `target/release/` |
| `ithmb-gen` | `ithmb-gen`(示例生成器二进制文件) | `target/release/` |
### 交叉编译
为其他目标进行交叉编译需要通过 `rustup target add` 安装相应的目标工具链:
```
# Linux x86-64 (x64 主机上的默认设置)
cargo build --release
# Linux ARM64 (aarch64)
rustup target add aarch64-unknown-linux-gnu
cargo build --release --target aarch64-unknown-linux-gnu
# macOS ARM64
rustup target add aarch64-apple-darwin
cargo build --release --target aarch64-apple-darwin
# Windows x64 (从 Linux 交叉编译)
rustup target add x86_64-pc-windows-gnu
cargo build --release --target x86_64-pc-windows-gnu
```
启用 SIMD 加速:
```
cargo build --release --features simd
```
可用特性:`simd`(SSE2/AVX2/NEON YUV 转换)、`cache`(LRU 原始文件缓存)、`metrics`(解码时间计数器)。
## 测试与验证
```
cargo test
```
跨越 12 个套件的 **486+ 个测试**:roundtrip(RGB565:65,536 个值,RGB555:32,768 个)、fuzz(覆盖所有 8 个解码器的 350+ 个输入 + 10,000 次随机字节突变)、2 个 libfuzzer 目标(120 万+ 次迭代,0 次崩溃)、并发压力测试、统计验证 + golden vector 验证、YUV 容差、解析器、推测性解码器路径(CL、CLCL、旋转、色度交换)、buffer-too-small 防护、trailing-padding 容差、JPEG carving 回退、多帧原始解码、旋转 roundtrip、BGR15 通道交换、PhotoDB roundtrip 写入/完整性/JPEG blob 解码、特定设备格式表、损坏 fuzz、格式 ID 配置测试、编码器辅助工具(隔行场 + BT.601 颜色转换)以及解码器回退路径。
整个工作区的 **12 个测试套件**,全部通过。
**真实设备验证:**
- **iPod Classic 6G (Reuhno):** 成功解码了真实的 F1061/F1055/F1060 .ithmb 文件(BGR15 通道交换,MSB 复制 —— 均确认正确)。30 个参考 PNG 与解码器输出匹配。
- **iOpenPod (TheRealSavi):** 在购买并测试的多个 iPod 型号上经验性地验证了 50+ 个配置。确认“iPod Nano 和 iPod Classic 型号没有已知问题”。我们的 54 个配置源自相同的格式 ID 源 —— 硬件验证由 iOpenPod 的测试涵盖。参见 [iOpenPod#140](https://github.com/TheRealSavi/iOpenPod/issues/140)。
- **iPhone 5 (iOS 7):** 956 个 T 前缀文件 —— 100% 提取
- **Jakarade.com F00-F08:** 227 个公开的 T 前缀文件 —— 100% JPEG+EXIF 检测
- **MVS CTF 2026 (iOS 18):** 扫描了 iPhone 14 Plus 的完整文件系统映像 —— 找到了 3 个 `.ithmb` 文件,但使用的是不同的专有格式(iOS Photos 框架,此编解码器无法解码)
## 架构
该项目被组织为一个包含五个 crate 的 Rust 工作区:
### ithmb-core(库)
核心解码库。所有解码器逻辑都位于此处;用于 FFI、CLI 或其他语言的封装都会调用此 crate。
按领域组织的 **21 个模块**:
| 模块 | 用途 |
|--------|---------|
| `pipeline.rs` | 中央分发 —— 读取格式前缀,分发到正确的解码器,应用裁剪/旋转后处理;接受 `&AtomicBool` 用于取消 |
| `jpeg.rs` | JPEG 解码器封装(`jpeg-decoder` crate),EXIF 方向解析 |
| `rgb565.rs` | RGB565 解码器(16 位 RGB 5/6/5) |
| `rgb555.rs` | RGB555 解码器(15 位 RGB 5/5/5) |
| `reordered_rgb555.rs` | 重排序的 RGB555 解码器(字节交换变体) |
| `uyvy.rs` | UYVY 4:2:2 + 隔行 UYVY 解码器(使用 `--features simd` 时 YUV→BGRA 采用 SSE2/AVX2/NEON) |
| `ycbcr420.rs` | YCbCr 4:2:0 平面解码器(使用 `--features simd` 时 YUV→BGRA 采用 SSE2/AVX2/NEON) |
| `clcl.rs` | CLCL nibble-chroma 解码器(使用 `--features simd` 时 YUV→BGRA 采用 SSE2/AVX2/NEON) |
| `cl.rs` | CL per-pixel chroma 解码器(使用 `--features simd` 时 YUV→BGRA 采用 SSE2/AVX2/NEON) |
| `yuv.rs` | 共享的 YUV 转换辅助工具,SSE2/AVX2/NEON 运行时分发 |
| `simd.rs` | SSE2/AVX2/NEON YUV 转换分发(特性门控) |
| `device_profiles.rs` | 18 个设备的 iPod/iPhone 格式查找表 |
| `enc.rs` | 用于所有原始格式的合成编码器 |
| `enc_helpers.rs` | 共享的编码器辅助工具(InterlaceFields, BT.601) |
| `profile.rs` | 配置结构体(IthmbVariantProfile, IthmbEncoding) |
| `profile_db.rs` | 内置配置数据库(54 个条目) |
| `profile_parser.rs` | 外部 `profiles.json` 的 JSON 解析器 |
| `cache.rs` | LRU 原始文件缓存(特性门控) |
| `metrics.rs` | 解码时间计数器(特性门控) |
| `error.rs` | 类型化错误枚举(`DecodeError`)+ 解码后的图像类型(`DecodedImage`) |
| `photodb/` | PhotoDB/ArtworkDB 块解析器、写入器、完整性检查器和类型定义 |
**数据流**
```
.ithmb file → JPEG/EXIF scan ──→ JPEG slice → jpeg-decoder crate → BGRA
├─ No JPEG → prefix lookup → raw decoder → BGRA
│ └→ no prefix + JPEG scan → byte-level SOI carving → jpeg-decoder → BGRA
│ └→ no prefix + mhfd magic → PhotoDB parser → entries → raw decoder → BGRA
└─ external .ithmb reference → read file → raw decoder → BGRA
```
**多帧支持** — F 前缀 `.ithmb` 文件可能包含多个串联的原始帧(由 Keith 的 iPod Photo Reader、ithmbrdr、libgpod 和 iOpenPod 确认)。编解码器从文件大小检测帧数。调用者可以通过帧索引(从 0 开始)访问各个帧;超出范围的索引将返回错误。嵌入 JPEG 的 T 前缀文件始终为单帧。
### ithmb-cli(CLI 二进制文件)
用于解码、检查和分析 `.ithmb` 文件的命令行工具。使用 `clap` 进行参数解析,并使用 `png` crate 输出 PNG。
```
# 将文件解码为 PNG
ithmb input.ithmb output.png
# 仅打印文件 metadata
ithmb --info input.ithmb
# 列出所有已知 profiles
ithmb --list-profiles
# 从多帧文件中提取特定帧
ithmb --frame 2 input.ithmb output.png
# Raw BGRA 输出 (无 PNG 编码)
ithmb --raw input.ithmb output.bin
```
### ithmb-core-cabi(C ABI 动态库)
一个 `cdylib`,通过 `ig_plugin_get_api()` 实现了 ImageGlass v10 原生插件 ABI,从而能够集成到 Windows 上的 ImageGlass 图像查看器中。C ABI 层将所有解码逻辑委托给 `ithmb-core`。它与核心库分开构建,仅在集成 ImageGlass 插件时需要。
### ithmb-python(PyO3 绑定)
一个 `cdylib`,通过 PyO3 (abi3-py312) 将 ithmb-core 暴露给 Python 3.12+。使用 `maturin build` 构建。
### ithmb-gen(示例生成器)
一个 CLI 工具,用于生成开发过程中使用的合成 `.ithmb` 测试向量和参考 PNG。

## CLI 工具
`ithmb` CLI 工具支持四种模式:
| 命令 | 描述 |
|---------|-------------|
| `ithmb input.ithmb [output.png]` | 解码为 PNG(根据扩展名自动检测格式) |
| `ithmb --info input.ithmb` | 打印元数据(大小、前缀、配置、帧数) |
| `ithmb --list-profiles` | 将 54 个配置的数据库打印为格式化表格 |
| `ithmb --frame N input.ithmb [output.png]` | 从多帧文件中提取第 N 帧 |
输出选项:使用 `--raw` 输出原始 BGRA 二进制数据,使用 `--format bin` 指定输出二进制格式,扩展名为 `.png` 时自动选择输出 PNG。
## 基准测试
解码吞吐量(divan,使用 `--features simd` 解码 256×256):
| 解码器 | 时间 | 吞吐量 |
|---------|------|-----------|
| RGB565 | 34 µs | 7.8 GB/s |
| RGB555 | 41 µs | 6.4 GB/s |
| ReorderedRGB555 | 365 µs | 718 MB/s |
| UYVY | 105 µs | 2.5 GB/s |
| YCbCr 4:2:0 | 103 µs | 2.6 GB/s |
| CLCL | ~200 µs | ~1.3 GB/s |
| CL | ~200 µs | ~1.3 GB/s |
| Pipeline (decode_ithmb) | 127 µs | 2.1 GB/s |
运行命令:`cargo bench --features simd`
## C ABI
`ithmb-core-cabi` crate 编译为 `cdylib`(`.so`/`.dylib`/`.dll`),暴露了 ImageGlass v10 插件 ABI 入口点 `ig_plugin_get_api()`。这允许:
- 在 Windows 上与 [ImageGlass](https://imageglass.org) 集成,以进行原生的 `.ithmb` 查看
- 从 C/C++、Python(通过 `ctypes`/`cffi`)或任何支持 C FFI 的语言进行 FFI 集成
- 无需子进程调用的零开销跨语言解码
## 配置参考
**54 个已知配置**(+ 1 个推测性禁用的配置 —— 参见代码库中的注释),涵盖从 iPod Photo 4G 到 iPhone 2G 以及 iPod Nano 7G 的设备。最大帧大小:480×864 (RGB565, 830 KB)。有关包含尺寸、编码和设备映射的完整表格,请参见 [PROFILES.md](PROFILES.md)。可以通过 `profiles.json` 在运行时添加外部配置。
每个配置定义了像素编码、尺寸、每帧的字节长度以及后处理标志(裁剪、旋转、通道交换、尺寸交换、隔行扫描、填充)。
## 限制
## 故障排除
| 症状 | 可能原因 / 解决方法 |
| ---------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| 文件无法打开 | 可能使用了未知的格式变体。请[提交编解码器 issue](https://github.com/B67687/ithmb-codec/issues)并附带样本。 |
| 图像乱码 / 颜色错误 | JPEG 误报或原始解码器不匹配(罕见)。请[提交编解码器 issue](https://github.com/B67687/ithmb-codec/issues)。 |
| “File too large” 错误 | 文件超过了 **32 MB** 限制 —— 正常的 iPhone 照片不应出现此情况。如果发生,请提交 issue。 |
## 开发
该库是通过迭代的研究、实现、审查和发布周期开发而成的:
1. **格式调查** — 发现并分析了 33 个开源 .ithmb 实现
2. **格式表提取** — iOpenPod(50+ 个条目)、libgpod、iLounge 讨论帖以及 Keith 的 iPod Photo Reader 为 54 个配置提供了尺寸/编码表
3. **实现** — 纯 Rust 工作区,包含 8 个解码器、JPEG 解码、PhotoDB/ArtworkDB 支持、CLI 工具、PyO3 Python 绑定和示例生成器
4. **测试** — 跨越 roundtrip、fuzz、libfuzzer、解析器、推测性路径、buffer-too-small 防护、trailing-padding 容差、JPEG carving 回退、多帧原始解码、旋转 roundtrip、字节级损坏 fuzz、BGR15 通道交换、PhotoDB roundtrip 写入、PhotoDB 完整性、PhotoDB JPEG blob 解码、特定设备格式表、并发压力测试以及格式 ID 配置测试的 486+ 个单元测试
5. **审查周期** — 5 轮多智能体审查:修复了约 47 项发现,涵盖内存安全、线程、ABI 兼容性、缓冲区溢出、整数溢出和纵深防御
6. **发布** — 通过 GitHub Releases 发布

完整版本历史请参见 [CHANGELOG.md](CHANGELOG.md)。
### 质量流水线
发布前在本地运行的质量检查:
```
cargo clippy --all-targets -- -D warnings # Lint
cargo test # All tests (486+ across 12 suites)
cargo audit # Advisory check
cargo fuzz build # Fuzz targets compile check
```
## 对生态系统的贡献
除了构建一个可用的编解码器外,该项目还为 .ithmb 逆向工程领域做出了几项原创性贡献:
- **多 OSS 格式合并** — 从 **22 个独立的实现**(iOpenPod、libgpod、Keith's iPod Photo Reader、clickwheel、gnupod、pygpod、ithmb-rs、OrgZ、andrewmalta/ithmb、wrinklykong/pyithmb、Reuhno、podkit、Steee29、keyj (Jeff Luyten)、Mixtape 等)中提取格式表,并将它们相互之间以及与现有表进行交叉比对。在设备配置中发现了 **15 处尺寸差异**,包括倒置的 Nano 5G/6G 配置、错误的 Nano 3G 格式,以及根据真实 iPhone 2G (iOS 1.1.4) 样本对 iOS 1.x 配置的修正。识别出 **18 个未出现在任何单一实现表中的格式 ID**。合并后的交叉参考涵盖了 **54 个唯一的格式 ID** —— 这是最完整的公开参考。
- **特定设备格式表** — 所有先前的工具都维护着所有已知格式 ID 的扁平列表。该项目映射了 **18 代 iPod/iPhone** 实际进行缩略图显示和封面艺术展示时所需的格式,从而使同步工具能够进行按设备的配置选择。
- **PhotoDB/ArtworkDB 写入支持** — 所有现有工具都是只读的(从设备的照片数据库中提取缩略图)。该项目实现了 `TryBuildPhotoDb`,能够从零开始编写有效的 ArtworkDB 二进制文件 —— 从而实现无需 iTunes 即可将封面艺术同步到 iPod。
- **通过社区进行硬件验证** — 发起了与 iOpenPod 的跨项目合作,其开发者购买了多个 iPod 型号,并跨固件世代验证了解码器。这填补了一个长期存在的空白:以前没有任何 OSS .ithmb 解码器进行过系统的硬件确认。
- **32 MB 文件大小限制(从头研究)** — 所有先前的解码器都引用 libgpod 的 256 MB 限制,但没有证据确认它是一个真实的固件常量。该项目独立推导出了 32 MB:跨 **54 个配置** 的最大帧大小为 829 KB,来自 5 个 RE 工具的多帧串联从未超过 ~40 帧,并且公开的 .ithmb 文件调查发现没有大于 1 MB 的文件。32 MB 是 2 的幂,涵盖了所有已知数据。于 2026-06-30 重新验证:40×P1007 = 31.64 MB(余量 376 KB)。
- **BGR15 iPhone 兼容性** — 通过真实的 iPod Classic 6G 样本 (Reuhno) 确认,iPhone 缩略图使用反向通道顺序(使用 `xBBBBBGGGGGRRRRR` 而不是标准的 `xRRRRRGGGGGBBBBB`)。添加了 `SwapRgbChannels` 标志 —— 这是第一个将 iPhone 像素布局与 iPod 布局区分开来的解码器。
- **推测性配置更正** — F1064 配置(320×240 YCbCr)在社区推测中流传多年。与每个公开实现进行了交叉检查:均未包含。已将其禁用并说明了理由。还将 CLCL nibble 缩放比例从 ×17(最初的 2005 Whirlpool RE)更正为 ×16,并与 2 个独立的实现进行了交叉验证。
- **合成测试向量 (CC0)** — 在此项目之前,不存在公开的 F 前缀测试数据。Reuhno 贡献了生成的 CC0 向量,涵盖了 3 种插槽几何结构(带有不同内容矩形的 56×55 插槽、128×128、320×320)以及 30 个参考 PNG。这些是用于原始 .ithmb 解码的首批公开测试向量。
- **负面认知:iOS Photos ≠ iPod Classic** — 下载并分析了两个 iOS 固件映像(9.3.5 和 iOS 18),确认它们的 .ithmb 文件使用的是完全不同的、此编解码器无法解码的专有格式。记录了关于 .ithmb 跨平台兼容性的一个常见误解。
## 更新日志
版本历史请参见 [CHANGELOG.md](CHANGELOG.md)。
## 许可证
MIT — 详见 [LICENSE](LICENSE)。
最初的 IthmbDecoder 参考实现(PR [#2316](https://github.com/d2phap/ImageGlass/pull/2316))是 GPL-3.0 协议。本库是一个净室实现,参考了该 PR 中描述的格式行为,但未使用任何 GPL 代码。
标签:Apple, ImageGlass插件, Rust, 可视化界面, 图像处理, 多媒体工具, 文件格式解析, 编解码器, 网络流量审计, 通知系统