Skip to main content

yscv_imgproc/ops/
intensity.rs

1use yscv_tensor::Tensor;
2
3use super::super::ImgProcError;
4use super::super::shape::hwc_shape;
5
6/// Applies gamma correction to each pixel: `pixel^gamma`.
7///
8/// Input is `[H, W, C]` with values typically in `[0, 1]`.
9/// Negative pixel values are clamped to 0 before the power operation.
10pub fn adjust_gamma(img: &Tensor, gamma: f32) -> Result<Tensor, ImgProcError> {
11    let (h, w, c) = hwc_shape(img)?;
12    let data = img.data();
13    let mut out = vec![0.0f32; h * w * c];
14
15    for i in 0..h * w * c {
16        out[i] = data[i].max(0.0).powf(gamma);
17    }
18
19    Tensor::from_vec(vec![h, w, c], out).map_err(Into::into)
20}
21
22/// Linearly rescales pixel intensities from `[in_min, in_max]` to `[out_min, out_max]`.
23///
24/// Values below `in_min` are clamped to `out_min`, values above `in_max` to `out_max`.
25/// Input is `[H, W, C]`.
26pub fn rescale_intensity(
27    img: &Tensor,
28    in_min: f32,
29    in_max: f32,
30    out_min: f32,
31    out_max: f32,
32) -> Result<Tensor, ImgProcError> {
33    let (h, w, c) = hwc_shape(img)?;
34    let data = img.data();
35    let mut out = vec![0.0f32; h * w * c];
36
37    let in_range = in_max - in_min;
38    let out_range = out_max - out_min;
39
40    if in_range.abs() < 1e-10 {
41        // Degenerate input range: map everything to out_min
42        for i in 0..h * w * c {
43            out[i] = out_min;
44        }
45    } else {
46        let scale = out_range / in_range;
47        for i in 0..h * w * c {
48            let v = (data[i] - in_min) * scale + out_min;
49            out[i] = v.clamp(out_min.min(out_max), out_min.max(out_max));
50        }
51    }
52
53    Tensor::from_vec(vec![h, w, c], out).map_err(Into::into)
54}
55
56/// Applies logarithmic transform: `log(1 + pixel)`, normalized to `[0, 1]`.
57///
58/// Input is `[H, W, C]` with non-negative values.
59/// The result is scaled so that the maximum output value is 1.0.
60pub fn adjust_log(img: &Tensor) -> Result<Tensor, ImgProcError> {
61    let (h, w, c) = hwc_shape(img)?;
62    let data = img.data();
63    let mut out = vec![0.0f32; h * w * c];
64
65    let mut max_val = 0.0f32;
66    for i in 0..h * w * c {
67        let v = (1.0 + data[i].max(0.0)).ln();
68        out[i] = v;
69        if v > max_val {
70            max_val = v;
71        }
72    }
73
74    // Normalize to [0, 1]
75    if max_val > 1e-10 {
76        let inv = 1.0 / max_val;
77        for v in &mut out {
78            *v *= inv;
79        }
80    }
81
82    Tensor::from_vec(vec![h, w, c], out).map_err(Into::into)
83}