fleischwolf_pdf/
resample.rs1use image::{Rgb, RgbImage};
7
8fn area_weights(src: usize, dst: usize, scale: f64) -> Vec<Vec<(usize, f64)>> {
10 (0..dst)
11 .map(|d| {
12 let f1 = d as f64 * scale;
13 let f2 = (d + 1) as f64 * scale;
14 let s1 = f1.floor() as usize;
15 let s2 = (f2.ceil() as usize).min(src);
16 (s1..s2)
17 .map(|si| {
18 let w = (((si + 1) as f64).min(f2) - (si as f64).max(f1)) / scale;
19 (si, w)
20 })
21 .collect()
22 })
23 .collect()
24}
25
26pub fn inter_area(src: &RgbImage, dw: u32, dh: u32) -> RgbImage {
29 let (sw, sh) = (src.width() as usize, src.height() as usize);
30 let (dwu, dhu) = (dw as usize, dh as usize);
31 let hw = area_weights(sw, dwu, sw as f64 / dw as f64);
32 let vw = area_weights(sh, dhu, sh as f64 / dh as f64);
33
34 let mut tmp = vec![[0f64; 3]; sh * dwu]; for y in 0..sh {
36 let row = y * dwu;
37 for (dx, ws) in hw.iter().enumerate() {
38 let mut acc = [0f64; 3];
39 for &(si, w) in ws {
40 let p = src.get_pixel(si as u32, y as u32);
41 acc[0] += p[0] as f64 * w;
42 acc[1] += p[1] as f64 * w;
43 acc[2] += p[2] as f64 * w;
44 }
45 tmp[row + dx] = acc;
46 }
47 }
48 let mut out = RgbImage::new(dw, dh);
49 for (dy, ws) in vw.iter().enumerate() {
50 for dx in 0..dwu {
51 let mut acc = [0f64; 3];
52 for &(si, w) in ws {
53 let t = tmp[si * dwu + dx];
54 acc[0] += t[0] * w;
55 acc[1] += t[1] * w;
56 acc[2] += t[2] * w;
57 }
58 out.put_pixel(
59 dx as u32,
60 dy as u32,
61 Rgb([round_u8(acc[0]), round_u8(acc[1]), round_u8(acc[2])]),
62 );
63 }
64 }
65 out
66}
67
68fn round_u8(v: f64) -> u8 {
69 v.round().clamp(0.0, 255.0) as u8
70}