1use image::{ImageBuffer, Luma, LumaA, Pixel, Rgb, Rgba};
4use std::{i16, u16, u8};
5
6pub type Image<P> = ImageBuffer<P, Vec<<P as Pixel>::Subpixel>>;
14
15pub trait HasBlack {
17 fn black() -> Self;
19}
20
21pub trait HasWhite {
23 fn white() -> Self;
25}
26
27macro_rules! impl_black_white {
28 ($for_:ty, $min:expr, $max:expr) => {
29 impl HasBlack for $for_ {
30 fn black() -> Self {
31 $min
32 }
33 }
34
35 impl HasWhite for $for_ {
36 fn white() -> Self {
37 $max
38 }
39 }
40 };
41}
42
43impl_black_white!(Luma<u8>, Luma([u8::MIN]), Luma([u8::MAX]));
44impl_black_white!(Luma<u16>, Luma([u16::MIN]), Luma([u16::MAX]));
45impl_black_white!(
46 LumaA<u8>,
47 LumaA([u8::MIN, u8::MAX]),
48 LumaA([u8::MAX, u8::MAX])
49);
50impl_black_white!(
51 LumaA<u16>,
52 LumaA([u16::MIN, u16::MAX]),
53 LumaA([u16::MAX, u16::MAX])
54);
55impl_black_white!(Rgb<u8>, Rgb([u8::MIN; 3]), Rgb([u8::MAX; 3]));
56impl_black_white!(Rgb<u16>, Rgb([u16::MIN; 3]), Rgb([u16::MAX; 3]));
57impl_black_white!(
58 Rgba<u8>,
59 Rgba([u8::MIN, u8::MIN, u8::MIN, u8::MAX]),
60 Rgba([u8::MAX, u8::MAX, u8::MAX, u8::MAX])
61);
62impl_black_white!(
63 Rgba<u16>,
64 Rgba([u16::MIN, u16::MIN, u16::MIN, u16::MAX]),
65 Rgba([u16::MAX, u16::MAX, u16::MAX, u16::MAX])
66);
67
68pub trait Position {
70 fn x(&self) -> u32;
72 fn y(&self) -> u32;
74}
75
76pub trait Score {
78 fn score(&self) -> f32;
80}
81
82pub trait Clamp<T> {
85 fn clamp(x: T) -> Self;
87}
88
89macro_rules! implement_clamp {
91 ($from:ty, $to:ty, $min:expr, $max:expr, $min_from:expr, $max_from:expr) => {
92 impl Clamp<$from> for $to {
93 fn clamp(x: $from) -> $to {
94 if x < $max_from as $from {
95 if x > $min_from as $from {
96 x as $to
97 } else {
98 $min
99 }
100 } else {
101 $max
102 }
103 }
104 }
105 };
106}
107
108macro_rules! implement_identity_clamp {
110 ( $($t:ty),* ) => {
111 $(
112 impl Clamp<$t> for $t {
113 fn clamp(x: $t) -> $t { x }
114 }
115 )*
116 };
117}
118
119implement_clamp!(i16, u8, u8::MIN, u8::MAX, u8::MIN as i16, u8::MAX as i16);
120implement_clamp!(u16, u8, u8::MIN, u8::MAX, u8::MIN as u16, u8::MAX as u16);
121implement_clamp!(i32, u8, u8::MIN, u8::MAX, u8::MIN as i32, u8::MAX as i32);
122implement_clamp!(u32, u8, u8::MIN, u8::MAX, u8::MIN as u32, u8::MAX as u32);
123implement_clamp!(f32, u8, u8::MIN, u8::MAX, u8::MIN as f32, u8::MAX as f32);
124implement_clamp!(f64, u8, u8::MIN, u8::MAX, u8::MIN as f64, u8::MAX as f64);
125
126implement_clamp!(
127 i32,
128 u16,
129 u16::MIN,
130 u16::MAX,
131 u16::MIN as i32,
132 u16::MAX as i32
133);
134implement_clamp!(
135 f32,
136 u16,
137 u16::MIN,
138 u16::MAX,
139 u16::MIN as f32,
140 u16::MAX as f32
141);
142implement_clamp!(
143 f64,
144 u16,
145 u16::MIN,
146 u16::MAX,
147 u16::MIN as f64,
148 u16::MAX as f64
149);
150
151implement_clamp!(
152 i32,
153 i16,
154 i16::MIN,
155 i16::MAX,
156 i16::MIN as i32,
157 i16::MAX as i32
158);
159
160implement_identity_clamp!(u8, i8, u16, i16, u32, i32, u64, i64, f32, f64);
161
162#[cfg(test)]
163mod tests {
164 use super::Clamp;
165
166 #[test]
167 fn test_clamp_f32_u8() {
168 let t: u8 = Clamp::clamp(255f32);
169 assert_eq!(t, 255u8);
170 let u: u8 = Clamp::clamp(300f32);
171 assert_eq!(u, 255u8);
172 let v: u8 = Clamp::clamp(0f32);
173 assert_eq!(v, 0u8);
174 let w: u8 = Clamp::clamp(-5f32);
175 assert_eq!(w, 0u8);
176 }
177
178 #[test]
179 fn test_clamp_f32_u16() {
180 let t: u16 = Clamp::clamp(65535f32);
181 assert_eq!(t, 65535u16);
182 let u: u16 = Clamp::clamp(300000f32);
183 assert_eq!(u, 65535u16);
184 let v: u16 = Clamp::clamp(0f32);
185 assert_eq!(v, 0u16);
186 let w: u16 = Clamp::clamp(-5f32);
187 assert_eq!(w, 0u16);
188 }
189}