From a4d4dcef3da69c3153ba701553edb607ff75dd58 Mon Sep 17 00:00:00 2001 From: admin Date: Tue, 28 Apr 2026 00:58:41 +0000 Subject: [PATCH] feat: full-resolution lightbox viewer - Thumbnails remain 300px for fast page load - Clicking image opens full-res version in lightbox - Full-res embedded as data-full attribute per image --- src/review.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/review.rs b/src/review.rs index d24f971..ec9bce2 100644 --- a/src/review.rs +++ b/src/review.rs @@ -153,6 +153,27 @@ fn make_thumbnail_data_uri(path: &std::path::Path) -> String { format!("data:image/jpeg;base64,{b64}") } +fn make_fullres_data_uri(path: &std::path::Path) -> String { + let data = match fs::read(path) { + Ok(d) => d, + Err(_) => return String::from("data:image/png;base64,"), + }; + + let img = match image::ImageReader::new(std::io::Cursor::new(&data)) + .with_guessed_format() + .ok() + .and_then(|r| r.decode().ok()) + { + Some(i) => i, + None => return String::from("data:image/png;base64,"), + }; + + let mut buf = std::io::Cursor::new(Vec::new()); + img.write_to(&mut buf, image::ImageFormat::Jpeg).unwrap_or(()); + let b64 = base64::engine::general_purpose::STANDARD.encode(buf.into_inner()); + format!("data:image/jpeg;base64,{b64}") +} + fn build_review_html(groups: &[DuplicateGroup]) -> String { let mut html = String::from(r#" @@ -233,6 +254,7 @@ h1 { text-align: center; margin-bottom: 20px; color: #e94560; } for (pidx, path) in group.paths.iter().enumerate() { let data_uri = make_thumbnail_data_uri(path); + let full_uri = make_fullres_data_uri(path); let display_path = path.display(); let size = fs::metadata(path) .map(|m| format_size(m.len())) @@ -240,7 +262,7 @@ h1 { text-align: center; margin-bottom: 20px; color: #e94560; } html.push_str(&format!( r#"
-{display_path} +{display_path}
{display_path}
{size}