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:
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user