feat(palette-extract): 补 bmp 解码器(复审 r1 p2-2,定案加)

M73 的 Windows 壁纸探测只读注册表/.theme 里的路径,不筛扩展名,.bmp 壁纸真会出现;
image 的 bmp 是独立 feature 且无额外传递依赖(bmp = []),代价≈0。
- features 加 "bmp",Cargo.toml 与 lib.rs 注释的口径对齐(原来注释说支持 bmp 但没开)
- 新增 bmp_is_supported(真编一张 BMP 再解码取色)
This commit is contained in:
AskaEth committed 2026-11-02 11:05:00 +08:00
1 parent 2ce394fbfc
commit 579f3ae271
3 files changed
+29 -5

No files matched your search

+10 -4
View File
@@ -16,11 +16,17 @@ unlucky-design = { path = "../design", version = "0.1" }
# 只开两个编解码器(MIT OR Apache-2.0,deny.toml 白名单内):
# - png:启动器背景图最常见的无损格式,也是截图通道用的格式;
# - jpeg:Windows 壁纸与用户照片的绝对主力(不引它等于「取色对一半用户不可用」)。
# - jpeg:Windows 壁纸与用户照片的绝对主力(不引它等于「取色对一半用户不可用」);
# - bmp:Windows 壁纸的真会出现(M73 的探测只读注册表/`.theme` 里的路径,**不筛扩展名**),
# 而 `image` 的 `bmp` 是独立 feature 且**无额外传递依赖**(`bmp = []`),代价≈0。
# 不开 `default-features`(默认会拖进 rayon + avif/ravif + webp + tiff + gif + exr + qoi
# 等一整套编码器,体积与审计面都翻倍);不开 webp/tiff/avif 是因为 M73 的壁纸探测拿到的
# 就是 png/jpg/bmp 三类,等真有人需要再单开一个 feature。
image = { workspace = true, default-features = false, features = ["png", "jpeg"] }
# 等一整套编码器,体积与审计面都翻倍);不开 webp/tiff/avif 是因为 M73 拿到的格式只有
# png/jpg/bmp 三类,等真有人需要再单开一个 feature。
image = { workspace = true, default-features = false, features = [
"png",
"jpeg",
"bmp",
] }
[lints]
workspace = true
+3 -1
View File
@@ -40,10 +40,12 @@
//!
//! 许可:`image` 是 `MIT OR Apache-2.0`,在 `deny.toml` 白名单内(`[licenses].allow`)。
//!
//! ## 体积影响(`image` 只开 png + jpeg,关掉 default-features)
//! ## 体积影响(`image` 只开 png + jpeg + bmp,关掉 default-features)
//!
//! 拉进的传递依赖就这几个:`png`(+ `fdeflate`/`miniz_oxide`/`crc32fast`/`flate2` 已在树里)、
//! `zune-jpeg` + `zune-core`、`byteorder-lite`、`num-traits`、`moxcms`/`pxfm`(色彩转换)。
//! `bmp` 是 `image` 的独立 feature 且**不带任何传递依赖**(`bmp = []`),加它只是因为
//! M73 的 Windows 壁纸探测不筛扩展名、`.bmp` 壁纸真会出现。
//! 关掉的默认特性里有 `rayon`(省一个线程池)、`avif`/`ravif`(最大的一个,编解码器整套)、
//! `webp`/`tiff`/`gif`/`exr`/`qoi`/`hdr`/`dds`/`ff`。实测增量见 M87 报告(`cargo tree` 前后对比)。
//!
+16
View File
@@ -61,6 +61,22 @@ fn extension_is_ignored_and_format_is_sniffed() {
assert_eq!((decoded.width(), decoded.height()), (16, 16));
}
#[test]
fn bmp_is_supported() {
// M73 的 Windows 壁纸探测不筛扩展名,`.bmp` 壁纸会真的出现在取色路径上。
// BMP 编码不是无损于色的(24 bit 存 RGB,这里是 32 bit Rgba),所以逐通道比对即可。
let mut bytes = Cursor::new(Vec::new());
DynamicImage::ImageRgba8(solid_image(32, 32, [0xB2, 0x3A, 0x48]))
.write_to(&mut bytes, ImageFormat::Bmp)
.expect("BMP 编码应当成功");
let seed = seed_from_bytes(&bytes.into_inner()).expect("BMP 应当能解码并取色");
assert_eq!(
seed.color,
unlucky_design::color::Color::rgb(0xB2, 0x3A, 0x48)
);
assert!(seed.chroma > 8.0);
}
#[test]
fn garbage_bytes_fail_and_map_to_undecodable() {
let loaded = decode_bytes(b"this is definitely not an image");