fix(theme): bound auto-theme image decode, spinner via event loop
Review follow-ups: extract_palette decoded the full image before the 100x100 downsample with no limits — a decompression-bomb PNG expands to tens of GB, and this box hard-freezes on OOM; decode is now bounded at 12k x 12k / 512 MB (any real wallpaper fits). The generating indicator is now set through upgrade_in_event_loop so the select_image path (which runs on a tokio thread, where a plain upgrade() returns None) shows it too. Startup generation stays synchronous by design: with the decode bounded it costs milliseconds and the first paint comes up in the generated palette instead of flashing the default. cc
This commit is contained in:
2 files changed
+20
-5
No files matched your search
@@ -13,7 +13,19 @@ pub fn extract_palette(image_path: &str) -> Result<ThemePalette, String> {
|
||||
return Err(format!("Image not found: {}", image_path));
|
||||
}
|
||||
|
||||
let img = image::open(path).map_err(|e| format!("Failed to open image: {}", e))?;
|
||||
// Bounded decode: a decompression-bomb PNG (65k x 65k) would otherwise
|
||||
// expand to tens of GB before the 100x100 downsample. 12k x 12k / 512 MB
|
||||
// covers any real wallpaper while keeping the worst case survivable.
|
||||
let mut reader = image::ImageReader::open(path)
|
||||
.map_err(|e| format!("Failed to open image: {}", e))?
|
||||
.with_guessed_format()
|
||||
.map_err(|e| format!("Failed to read image: {}", e))?;
|
||||
let mut limits = image::Limits::default();
|
||||
limits.max_image_width = Some(12_000);
|
||||
limits.max_image_height = Some(12_000);
|
||||
limits.max_alloc = Some(512 * 1024 * 1024);
|
||||
reader.limits(limits);
|
||||
let img = reader.decode().map_err(|e| format!("Failed to decode image: {}", e))?;
|
||||
|
||||
// Downsample to 100x100 for fast processing.
|
||||
let thumb = img.resize_exact(100, 100, image::imageops::FilterType::Lanczos3);
|
||||
|
||||
Reference in new issue
Block a user