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
This commit is contained in:
admin
2026-04-28 00:58:41 +00:00
parent a01f70018f
commit a4d4dcef3d

View File

@@ -153,6 +153,27 @@ fn make_thumbnail_data_uri(path: &std::path::Path) -> String {
format!("data:image/jpeg;base64,{b64}") 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 { fn build_review_html(groups: &[DuplicateGroup]) -> String {
let mut html = String::from(r#"<!DOCTYPE html> let mut html = String::from(r#"<!DOCTYPE html>
<html lang="en"> <html lang="en">
@@ -233,6 +254,7 @@ h1 { text-align: center; margin-bottom: 20px; color: #e94560; }
for (pidx, path) in group.paths.iter().enumerate() { for (pidx, path) in group.paths.iter().enumerate() {
let data_uri = make_thumbnail_data_uri(path); let data_uri = make_thumbnail_data_uri(path);
let full_uri = make_fullres_data_uri(path);
let display_path = path.display(); let display_path = path.display();
let size = fs::metadata(path) let size = fs::metadata(path)
.map(|m| format_size(m.len())) .map(|m| format_size(m.len()))
@@ -240,7 +262,7 @@ h1 { text-align: center; margin-bottom: 20px; color: #e94560; }
html.push_str(&format!( html.push_str(&format!(
r#"<div class="image-card" id="card-{idx}-{pidx}"> r#"<div class="image-card" id="card-{idx}-{pidx}">
<img src="{data_uri}" alt="{display_path}" title="Click for full size" onclick="openLightbox(this.src, '{display_path}')"> <img src="{data_uri}" data-full="{full_uri}" alt="{display_path}" title="Click for full size" onclick="openLightbox(this.dataset.full, '{display_path}')">
<div class="path">{display_path}</div> <div class="path">{display_path}</div>
<div class="size">{size}</div> <div class="size">{size}</div>
<label><input type="checkbox" class="del-check" data-group="{idx}" value="{display_path}"> Delete this</label> <label><input type="checkbox" class="del-check" data-group="{idx}" value="{display_path}"> Delete this</label>