white_balancer/math/
scale.rs1use std::ops::{Div, Mul};
2
3pub trait ToFromu8 {
4 fn to_u8(self) -> u8;
5 fn from_u8(v: u8) -> Self;
6 fn from_f32(v: f32) -> Self;
7}
8
9macro_rules! impl_to_from_u8 {
10 ($($ty:ty)*) => {
11 $(
12 impl ToFromu8 for $ty {
13 #[inline]
14 fn to_u8(self) -> u8 {
15 if self > Self::from(u8::max_value()) {
16 u8::max_value()
17 } else {
18 self as u8
19 }
20 }
21 #[inline]
22 fn from_u8(v: u8) -> $ty {
23 v as $ty
24 }
25 #[inline]
26 fn from_f32(v: f32) -> $ty {
27 v as $ty
28 }
29 }
30 )*
31 }
32}
33
34impl_to_from_u8!(f32 f64);
35
36#[inline]
37pub fn scale_pixel<T: ToFromu8>(pixel: u8, numerator: T, denominator: T) -> u8
38 where T: Clone + Mul<T, Output = T> + Div<T, Output = T>{
39 let res = T::from_u8(pixel) * numerator / denominator;
40 res.to_u8()
41}
42
43#[cfg(test)]
44mod test {
45 use super::*;
46
47 #[test]
48 fn test_normal_scaling() {
49 assert_eq!(scale_pixel(10u8, 2f32, 1f32), 20u8);
50 assert_eq!(scale_pixel(10u8, 1f32, 2f32), 5u8);
51 assert_eq!(scale_pixel(10u8, 2f64, 1f64), 20u8);
52 assert_eq!(scale_pixel(10u8, 1f64, 2f64), 5u8);
53 }
54
55 #[test]
56 fn test_overflow() {
57 let new_pixel = scale_pixel(250, 2f32, 1f32);
58 assert_eq!(new_pixel, 255u8);
59 }
60}