convolve_image/
rescale.rs1#[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}