dicom_viewer/dcm/
thumbnail.rs1use anyhow::Result;
8use std::path::Path;
9
10use crate::dcm::pixel::{auto_window, load_raw};
11
12pub struct Thumbnail {
14 pub width: u32,
16 pub height: u32,
18 pub rgba: Vec<u8>,
20}
21
22pub fn load_thumbnail(path: &Path, max_dim: u32) -> Result<Thumbnail> {
27 let raw = load_raw(path)?;
28 let max_side = raw.width.max(raw.height);
29 let scale = max_side.div_ceil(max_dim).max(1);
30 let w = (raw.width / scale).max(1);
31 let h = (raw.height / scale).max(1);
32
33 let (center, width) = auto_window(&raw);
34 let w_f = width.max(1e-3);
35 let lo = center - w_f / 2.0;
36 let inv_w = 255.0 / w_f;
37 let invert = raw.photometric_invert;
38
39 let mut out = vec![0u8; (w * h * 4) as usize];
40 let src_w = raw.width as usize;
41 for y in 0..h {
42 let sy = (y * scale) as usize;
43 for x in 0..w {
44 let sx = (x * scale) as usize;
45 let v = raw.values[sy * src_w + sx] as f64;
46 let g = ((v - lo) * inv_w).round().clamp(0.0, 255.0) as u8;
47 let g = if invert { 255 - g } else { g };
48 let o = ((y * w + x) * 4) as usize;
49 out[o] = g;
50 out[o + 1] = g;
51 out[o + 2] = g;
52 out[o + 3] = 255;
53 }
54 }
55
56 Ok(Thumbnail {
57 width: w,
58 height: h,
59 rgba: out,
60 })
61}