use std::path::Path;
use anyhow::Result;
use image::DynamicImage;
pub fn create_thumbnail(path: &Path, max_dim: u32) -> Result<DynamicImage> {
let data = std::fs::read(path)?;
for jpeg in extract_jpeg_candidates(&data) {
if let Ok(img) = image::load_from_memory(&jpeg) {
return Ok(DynamicImage::from(img).thumbnail(max_dim, max_dim));
}
}
anyhow::bail!("X3F 无有效内嵌 JPEG 预览: {:?}", path)
}
fn extract_jpeg_candidates(data: &[u8]) -> Vec<Vec<u8>> {
let mut segments: Vec<Vec<u8>> = Vec::new();
let mut i = 0;
while i + 2 < data.len() {
if data[i] == 0xFF && data[i + 1] == 0xD8 {
if let Some(rel) = data[i + 2..]
.windows(2)
.position(|w| w[0] == 0xFF && w[1] == 0xD9)
{
let end = i + 2 + rel + 2;
segments.push(data[i..end].to_vec());
i = end;
continue;
}
}
i += 1;
}
segments.sort_by_key(|b| std::cmp::Reverse(b.len()));
segments
}
#[cfg(test)]
mod tests {
use super::*;
use std::path::Path;
#[test]
fn sigma_x3f_sample_has_preview() {
let path = Path::new(r"D:\xsmspace\data\1\file\RAW\RAW_SIGMA_DP1.X3F");
if !path.exists() {
return;
}
assert!(create_thumbnail(path, 512).is_ok());
}
}