jxl_render/vardct/generic/
mod.rs1use jxl_grid::{AlignedGrid, AllocTracker};
2
3mod dct;
4mod transform;
5#[allow(unused)]
6pub use dct::dct_2d;
7#[allow(unused)]
8pub use transform::*;
9
10#[inline(always)]
11pub fn adaptive_lf_smoothing_impl(
12 width: usize,
13 height: usize,
14 [in_x, in_y, in_b]: [&mut [f32]; 3],
15 [lf_x, lf_y, lf_b]: [f32; 3],
16 tracker: Option<&AllocTracker>,
17) -> crate::Result<()> {
18 const SCALE_SELF: f32 = 0.052262735;
19 const SCALE_SIDE: f32 = 0.2034514;
20 const SCALE_DIAG: f32 = 0.03348292;
21
22 if width <= 2 || height <= 2 {
23 return Ok(());
25 }
26
27 assert_eq!(in_x.len(), in_y.len());
28 assert_eq!(in_y.len(), in_b.len());
29 assert_eq!(in_x.len(), width * height);
30
31 let mut udsum_x = AlignedGrid::with_alloc_tracker(width, height - 2, tracker)?;
32 let mut udsum_y = AlignedGrid::with_alloc_tracker(width, height - 2, tracker)?;
33 let mut udsum_b = AlignedGrid::with_alloc_tracker(width, height - 2, tracker)?;
34
35 for (g, out) in [
36 (&mut *in_x, udsum_x.buf_mut()),
37 (&mut *in_y, udsum_y.buf_mut()),
38 (&mut *in_b, udsum_b.buf_mut()),
39 ] {
40 let up = g.chunks_exact(width);
41 let down = g[width * 2..].chunks_exact(width);
42 let out = out.chunks_exact_mut(width);
43 for ((up, down), out) in up.zip(down).zip(out) {
44 for ((&u, &d), out) in up.iter().zip(down).zip(out) {
45 *out = u + d;
46 }
47 }
48 }
49
50 let mut in_x_row = in_x.chunks_exact_mut(width).skip(1);
51 let mut in_y_row = in_y.chunks_exact_mut(width).skip(1);
52 let mut in_b_row = in_b.chunks_exact_mut(width).skip(1);
53
54 let mut udsum_x_row = udsum_x.buf_mut().chunks_exact(width);
55 let mut udsum_y_row = udsum_y.buf_mut().chunks_exact(width);
56 let mut udsum_b_row = udsum_b.buf_mut().chunks_exact(width);
57
58 loop {
59 let Some(udsum_x) = udsum_x_row.next() else {
60 break;
61 };
62 let udsum_y = udsum_y_row.next().unwrap();
63 let udsum_b = udsum_b_row.next().unwrap();
64 let in_x = in_x_row.next().unwrap();
65 let in_y = in_y_row.next().unwrap();
66 let in_b = in_b_row.next().unwrap();
67
68 let mut in_x_prev = in_x[0];
69 let mut in_y_prev = in_y[0];
70 let mut in_b_prev = in_b[0];
71 for x in 1..(width - 1) {
72 let x_self = in_x[x];
73 let x_side = in_x_prev + in_x[x + 1] + udsum_x[x];
74 let x_diag = udsum_x[x - 1] + udsum_x[x + 1];
75 let x_wa = x_self * SCALE_SELF + x_side * SCALE_SIDE + x_diag * SCALE_DIAG;
76 let x_gap_t = (x_wa - x_self).abs() / lf_x;
77
78 let y_self = in_y[x];
79 let y_side = in_y_prev + in_y[x + 1] + udsum_y[x];
80 let y_diag = udsum_y[x - 1] + udsum_y[x + 1];
81 let y_wa = y_self * SCALE_SELF + y_side * SCALE_SIDE + y_diag * SCALE_DIAG;
82 let y_gap_t = (y_wa - y_self).abs() / lf_y;
83
84 let b_self = in_b[x];
85 let b_side = in_b_prev + in_b[x + 1] + udsum_b[x];
86 let b_diag = udsum_b[x - 1] + udsum_b[x + 1];
87 let b_wa = b_self * SCALE_SELF + b_side * SCALE_SIDE + b_diag * SCALE_DIAG;
88 let b_gap_t = (b_wa - b_self).abs() / lf_b;
89
90 let gap = 0.5f32.max(x_gap_t).max(y_gap_t).max(b_gap_t);
91 let gap_scale = (3.0 - 4.0 * gap).max(0.0);
92
93 in_x[x] = (x_wa - x_self) * gap_scale + x_self;
94 in_y[x] = (y_wa - y_self) * gap_scale + y_self;
95 in_b[x] = (b_wa - b_self) * gap_scale + b_self;
96 in_x_prev = x_self;
97 in_y_prev = y_self;
98 in_b_prev = b_self;
99 }
100 }
101
102 Ok(())
103}