convolve_image/
rescale.rs

1#[cfg(feature = "image")]
2use std::cmp::Ordering;
3#[cfg(feature = "image")]
4use image::{DynamicImage, Rgb};
5
6#[cfg(feature = "ndarray")]
7use ndarray::{Array2, Array3};
8#[cfg(feature = "ndarray")]
9use crate::ndarray::Aggregate;
10
11#[derive(Copy, Clone)]
12pub enum RescaleRange {
13    Custom(f32, f32),
14    Max,
15}
16
17impl RescaleRange {
18    fn min(self) -> f32 {
19        match self {
20            RescaleRange::Custom(min, _) => min,
21            RescaleRange::Max => 0.
22        }
23    }
24
25    fn max(self) -> f32 {
26        match self {
27            RescaleRange::Custom(_, max) => max,
28            RescaleRange::Max => 1.
29        }
30    }
31}
32
33pub trait Rescale {
34    fn min(&self) -> f32;
35    fn max(&self) -> f32;
36    fn rescale(&mut self, range: RescaleRange);
37    fn channel_wise_rescale(&mut self, range: RescaleRange);
38    fn rescale_value(min: f32, max: f32, value: f32, range: RescaleRange) -> f32 {
39        let (new_min, new_max) = (range.min(), range.max());
40        let new_range = new_max - new_min;
41
42        new_min + ((value - min) * new_range / (max - min))
43    }
44}
45
46#[cfg(feature = "image")]
47impl Rescale for DynamicImage {
48    fn min(&self) -> f32 {
49        self
50            .to_rgb32f()
51            .iter()
52            .min_by(|x, y| {
53                if x > y {
54                    Ordering::Greater
55                } else if y > x {
56                    Ordering::Less
57                } else {
58                    Ordering::Equal
59                }
60            })
61            .copied()
62            .unwrap_or(0.)
63            .min(0.)
64    }
65
66    fn max(&self) -> f32 {
67        self
68            .to_rgb32f()
69            .iter()
70            .max_by(|x, y| {
71                if x > y {
72                    Ordering::Greater
73                } else if y > x {
74                    Ordering::Less
75                } else {
76                    Ordering::Equal
77                }
78            })
79            .copied()
80            .unwrap_or(1.)
81            .max(1.)
82    }
83
84    fn rescale(&mut self, range: RescaleRange) {
85        let min = self.min();
86        let max = self.max();
87
88        for pixel in self.to_rgb32f().pixels_mut() {
89            let [r, g, b] = pixel.0;
90            *pixel = Rgb([Self::rescale_value(min, max, r, range), Self::rescale_value(min, max, g, range), Self::rescale_value(min, max, b, range)]);
91        }
92    }
93
94    fn channel_wise_rescale(&mut self, range: RescaleRange) {
95        let mut max_r: f32 = 1.;
96        let mut max_g: f32 = 1.;
97        let mut max_b: f32 = 1.;
98
99        let mut min_r: f32 = 0.;
100        let mut min_g: f32 = 0.;
101        let mut min_b: f32 = 0.;
102
103        let mut source = self.to_rgb32f();
104
105        for pixel in source.pixels() {
106            let [r, g, b] = pixel.0;
107            max_r = max_r.max(r);
108            max_g = max_g.max(g);
109            max_b = max_b.max(b);
110
111            min_r = min_r.min(r);
112            min_g = min_g.min(g);
113            min_b = min_b.min(b);
114        }
115
116        for pixel in source.pixels_mut() {
117            let [r, g, b] = pixel.0;
118            *pixel = Rgb([
119                Self::rescale_value(min_r, max_r, r, range),
120                Self::rescale_value(min_g, max_g, g, range),
121                Self::rescale_value(min_b, max_b, b, range),
122            ]);
123        }
124    }
125}
126
127#[cfg(feature = "ndarray")]
128impl Rescale for Array2<f32> {
129    fn min(&self) -> f32 {
130        Aggregate::min(self)
131    }
132
133    fn max(&self) -> f32 {
134        Aggregate::max(self)
135    }
136
137    fn rescale(&mut self, range: RescaleRange) {
138        let min = Rescale::min(self);
139        let max = Rescale::max(self);
140
141        for item in self.iter_mut() {
142            *item = Self::rescale_value(min, max, *item, range);
143        }
144    }
145
146    fn channel_wise_rescale(&mut self, range: RescaleRange) {
147        self.rescale(range)
148    }
149}
150
151#[cfg(feature = "ndarray")]
152impl Rescale for Array3<f32> {
153    fn min(&self) -> f32 {
154        Aggregate::min(self)
155    }
156
157    fn max(&self) -> f32 {
158        Aggregate::max(self)
159    }
160
161    fn rescale(&mut self, range: RescaleRange) {
162        let min = Rescale::min(self);
163        let max = Rescale::max(self);
164
165        for item in self.iter_mut() {
166            *item = Self::rescale_value(min, max, *item, range);
167        }
168    }
169
170    fn channel_wise_rescale(&mut self, range: RescaleRange) {
171        let mut max_r: f32 = 1.;
172        let mut max_g: f32 = 1.;
173        let mut max_b: f32 = 1.;
174
175        let mut min_r: f32 = 0.;
176        let mut min_g: f32 = 0.;
177        let mut min_b: f32 = 0.;
178
179        for ((_, _, channel), item) in self.indexed_iter() {
180            match channel {
181                0 => {
182                    min_r = min_r.min(*item);
183                    max_r = max_r.max(*item);
184                }
185                1 => {
186                    min_g = min_g.min(*item);
187                    max_g = max_g.max(*item);
188                }
189                2 => {
190                    min_b = min_b.min(*item);
191                    max_b = max_b.max(*item);
192                }
193                _ => panic!("Unexpected number of channels")
194            };
195        }
196
197        for ((_, _, channel), item) in self.indexed_iter_mut() {
198            match channel {
199                0 => {
200                    *item = Self::rescale_value(min_r, max_r, *item, range);
201                }
202                1 => {
203                    *item = Self::rescale_value(min_g, max_g, *item, range);
204                }
205                2 => {
206                    *item = Self::rescale_value(min_b, max_b, *item, range);
207                }
208                _ => panic!("Unexpected number of channels")
209            };
210        }
211    }
212}