sophus_image/intensity_image/
intensity_mut_image.rs

1use sophus_autodiff::linalg::SVec;
2
3use crate::{
4    DynIntensityMutImage,
5    MutImage,
6    MutImageR,
7    intensity_image::{
8        dyn_intensity_image::DynIntensityMutImageU,
9        intensity_pixel::IntensityPixel,
10        intensity_scalar::IsIntensityScalar,
11    },
12    prelude::*,
13};
14
15/// Trait for "intensity" images (grayscale, grayscale+alpha, RGB, RGBA).
16///
17/// Hence it s a trait for grayscale (1-channel), grayscale+alpha (2-channel), RGB (3-channel), and
18/// RGBA images (4-channel).
19///
20/// This trait provides methods for converting between different image type. As of now, three
21/// scalar type are supported: `u8`, `u16`, and `f32`:
22///
23///  - u8 images are in the range [0, 255], i.e. 100% intensity corresponds to 255.
24///
25///  - u16 images are in the range [0, 65535], i.e. 100% intensity corresponds to 65535.
26///
27///  - f32 images shall be in the range [0.0, 1.0] and 100% intensity corresponds to 1.0. If the f32
28///    is outside this range, conversion results may be surprising.
29///
30/// These are image type which typically used for computer vision and graphics applications.
31pub trait IsIntensityMutImage<
32    Scalar: IsIntensityScalar + 'static,
33    Pixel: IntensityPixel<Scalar> + 'static,
34>: core::marker::Sized
35{
36    /// Pixel type
37    type Pixel<OtherScalar: IsIntensityScalar>: IntensityPixel<OtherScalar>;
38
39    /// Casted mutable image type
40    type CastedMutImage<OtherScalar: IsIntensityScalar>;
41
42    /// Converts the image to a grayscale image.
43    fn to_grayscale(img: Self) -> MutImage<Scalar>;
44
45    /// Converts the image to a grayscale_alpha image.
46    fn to_grayscale_alpha(img: Self) -> MutImageR<Scalar, 2>;
47
48    /// Converts the image to a RGB image.
49    fn to_rgb(img: Self) -> MutImageR<Scalar, 3>;
50
51    /// Converts the image to a RGBA image.
52    fn to_rgba(img: Self) -> MutImageR<Scalar, 4>;
53
54    /// Converts the image to a u8 image.
55    fn convert_to<OtherScalar: IsIntensityScalar>(img: Self) -> Self::CastedMutImage<OtherScalar>;
56}
57
58impl<Scalar: IsIntensityScalar + 'static> IsIntensityMutImage<Scalar, Scalar> for MutImage<Scalar> {
59    type Pixel<S: IsIntensityScalar> = S;
60
61    type CastedMutImage<OtherScalar: IsIntensityScalar> = MutImage<OtherScalar>;
62
63    fn to_grayscale(img: Self) -> MutImage<Scalar> {
64        img
65    }
66
67    fn to_grayscale_alpha(img: Self) -> MutImageR<Scalar, 2> {
68        MutImageR::<Scalar, 2>::from_map(&img.image_view(), |rgb: &Scalar| -> SVec<Scalar, 2> {
69            SVec::<Scalar, 2>::new(*rgb, Scalar::MAX)
70        })
71    }
72
73    fn to_rgb(img: Self) -> MutImageR<Scalar, 3> {
74        MutImageR::<Scalar, 3>::from_map(&img.image_view(), |rgb: &Scalar| -> SVec<Scalar, 3> {
75            SVec::<Scalar, 3>::new(*rgb, *rgb, *rgb)
76        })
77    }
78
79    fn to_rgba(img: Self) -> MutImageR<Scalar, 4> {
80        MutImageR::<Scalar, 4>::from_map(&img.image_view(), |rgb: &Scalar| -> SVec<Scalar, 4> {
81            SVec::<Scalar, 4>::new(*rgb, *rgb, *rgb, Scalar::MAX)
82        })
83    }
84
85    fn convert_to<OtherScalar: IsIntensityScalar>(img: Self) -> MutImage<OtherScalar> {
86        MutImage::<OtherScalar>::from_map(&img.image_view(), |rgb: &Scalar| -> OtherScalar {
87            OtherScalar::from(*rgb)
88        })
89    }
90}
91
92impl<Scalar: IsIntensityScalar + 'static> IsIntensityMutImage<Scalar, SVec<Scalar, 2>>
93    for MutImageR<Scalar, 2>
94{
95    type Pixel<S: IsIntensityScalar> = SVec<S, 2>;
96
97    type CastedMutImage<OtherScalar: IsIntensityScalar> = MutImageR<OtherScalar, 2>;
98
99    fn to_grayscale(img: Self) -> MutImage<Scalar> {
100        MutImage::<Scalar>::from_map(&img.image_view(), |rgba: &SVec<Scalar, 2>| -> Scalar {
101            rgba[0]
102        })
103    }
104
105    fn to_grayscale_alpha(img: Self) -> MutImageR<Scalar, 2> {
106        img
107    }
108
109    fn to_rgb(img: Self) -> MutImageR<Scalar, 3> {
110        MutImageR::<Scalar, 3>::from_map(
111            &img.image_view(),
112            |rgba: &SVec<Scalar, 2>| -> SVec<Scalar, 3> {
113                SVec::<Scalar, 3>::new(rgba[0], rgba[0], rgba[0])
114            },
115        )
116    }
117
118    fn to_rgba(img: Self) -> MutImageR<Scalar, 4> {
119        MutImageR::<Scalar, 4>::from_map(
120            &img.image_view(),
121            |rgba: &SVec<Scalar, 2>| -> SVec<Scalar, 4> {
122                SVec::<Scalar, 4>::new(rgba[0], rgba[0], rgba[0], rgba[1])
123            },
124        )
125    }
126
127    fn convert_to<OtherScalar: IsIntensityScalar>(img: Self) -> MutImageR<OtherScalar, 2> {
128        MutImageR::<OtherScalar, 2>::from_map(
129            &img.image_view(),
130            |rgba: &SVec<Scalar, 2>| -> SVec<OtherScalar, 2> {
131                SVec::<OtherScalar, 2>::new(rgba[0].cast_to(), rgba[1].cast_to())
132            },
133        )
134    }
135}
136
137impl<Scalar: IsIntensityScalar + 'static> IsIntensityMutImage<Scalar, SVec<Scalar, 3>>
138    for MutImageR<Scalar, 3>
139{
140    type Pixel<S: IsIntensityScalar> = SVec<S, 3>;
141
142    type CastedMutImage<OtherScalar: IsIntensityScalar> = MutImageR<OtherScalar, 3>;
143
144    fn to_grayscale(img: Self) -> MutImage<Scalar> {
145        MutImage::<Scalar>::from_map(&img.image_view(), |rgb: &SVec<Scalar, 3>| -> Scalar {
146            rgb[0]
147        })
148    }
149
150    fn to_grayscale_alpha(img: Self) -> MutImageR<Scalar, 2> {
151        MutImageR::<Scalar, 2>::from_map(
152            &img.image_view(),
153            |rgb: &SVec<Scalar, 3>| -> SVec<Scalar, 2> {
154                SVec::<Scalar, 2>::new(rgb[0], Scalar::MAX)
155            },
156        )
157    }
158
159    fn to_rgb(img: Self) -> MutImageR<Scalar, 3> {
160        img
161    }
162
163    fn to_rgba(img: Self) -> MutImageR<Scalar, 4> {
164        MutImageR::<Scalar, 4>::from_map(
165            &img.image_view(),
166            |rgb: &SVec<Scalar, 3>| -> SVec<Scalar, 4> {
167                SVec::<Scalar, 4>::new(rgb[0], rgb[1], rgb[2], Scalar::MAX)
168            },
169        )
170    }
171
172    fn convert_to<OtherScalar: IsIntensityScalar>(img: Self) -> MutImageR<OtherScalar, 3> {
173        MutImageR::<OtherScalar, 3>::from_map(
174            &img.image_view(),
175            |rgb: &SVec<Scalar, 3>| -> SVec<OtherScalar, 3> {
176                SVec::<OtherScalar, 3>::new(rgb[0].cast_to(), rgb[1].cast_to(), rgb[2].cast_to())
177            },
178        )
179    }
180}
181
182impl<Scalar: IsIntensityScalar + 'static> IsIntensityMutImage<Scalar, SVec<Scalar, 4>>
183    for MutImageR<Scalar, 4>
184{
185    type Pixel<S: IsIntensityScalar> = SVec<S, 4>;
186
187    type CastedMutImage<OtherScalar: IsIntensityScalar> = MutImageR<OtherScalar, 4>;
188
189    fn to_grayscale(img: Self) -> MutImage<Scalar> {
190        MutImage::<Scalar>::from_map(&img.image_view(), |rgba: &SVec<Scalar, 4>| -> Scalar {
191            rgba[0]
192        })
193    }
194
195    fn to_grayscale_alpha(img: Self) -> MutImageR<Scalar, 2> {
196        MutImageR::<Scalar, 2>::from_map(
197            &img.image_view(),
198            |rgba: &SVec<Scalar, 4>| -> SVec<Scalar, 2> {
199                SVec::<Scalar, 2>::new(rgba[0], rgba[3])
200            },
201        )
202    }
203
204    fn to_rgb(img: Self) -> MutImageR<Scalar, 3> {
205        MutImageR::<Scalar, 3>::from_map(
206            &img.image_view(),
207            |rgba: &SVec<Scalar, 4>| -> SVec<Scalar, 3> {
208                SVec::<Scalar, 3>::new(rgba[0], rgba[1], rgba[2])
209            },
210        )
211    }
212
213    fn to_rgba(img: Self) -> MutImageR<Scalar, 4> {
214        img
215    }
216
217    fn convert_to<OtherScalar: IsIntensityScalar>(img: Self) -> MutImageR<OtherScalar, 4> {
218        MutImageR::<OtherScalar, 4>::from_map(
219            &img.image_view(),
220            |rgba: &SVec<Scalar, 4>| -> SVec<OtherScalar, 4> {
221                SVec::<OtherScalar, 4>::new(
222                    rgba[0].cast_to(),
223                    rgba[1].cast_to(),
224                    rgba[2].cast_to(),
225                    rgba[3].cast_to(),
226                )
227            },
228        )
229    }
230}
231
232/// Trait for "intensity" images (grayscale, grayscale+alpha, RGB, RGBA).
233pub trait HasIntoDynIntensityMutImage<
234    Scalar: IsIntensityScalar + 'static,
235    Pixel: IntensityPixel<Scalar> + 'static,
236>: IsIntensityMutImage<Scalar, Pixel>
237{
238    /// Returns a dynamic representation of the image.
239    fn into_dyn(img: Self) -> DynIntensityMutImage;
240
241    /// Tries to return a dynamic image view of unsigned values.
242    ///
243    /// If the image is not of unsigned type, it returns None.
244    fn try_into_dyn_u(img: Self) -> Option<DynIntensityMutImageU>;
245}
246
247impl HasIntoDynIntensityMutImage<u8, u8> for MutImage<u8> {
248    fn into_dyn(img: Self) -> DynIntensityMutImage {
249        DynIntensityMutImage::GrayscaleU8(img)
250    }
251
252    fn try_into_dyn_u(img: Self) -> Option<DynIntensityMutImageU> {
253        Some(DynIntensityMutImageU::GrayscaleU8(img))
254    }
255}
256
257impl HasIntoDynIntensityMutImage<u16, u16> for MutImage<u16> {
258    fn into_dyn(img: Self) -> DynIntensityMutImage {
259        DynIntensityMutImage::GrayscaleU16(img)
260    }
261
262    fn try_into_dyn_u(img: Self) -> Option<DynIntensityMutImageU> {
263        Some(DynIntensityMutImageU::GrayscaleU16(img))
264    }
265}
266
267impl HasIntoDynIntensityMutImage<f32, f32> for MutImage<f32> {
268    fn into_dyn(img: Self) -> DynIntensityMutImage {
269        DynIntensityMutImage::GrayscaleF32(img)
270    }
271
272    fn try_into_dyn_u(_img: Self) -> Option<DynIntensityMutImageU> {
273        None
274    }
275}
276
277impl HasIntoDynIntensityMutImage<u8, SVec<u8, 2>> for MutImageR<u8, 2> {
278    fn into_dyn(img: Self) -> DynIntensityMutImage {
279        DynIntensityMutImage::GrayscaleAlphaU8(img)
280    }
281
282    fn try_into_dyn_u(img: Self) -> Option<DynIntensityMutImageU> {
283        Some(DynIntensityMutImageU::GrayscaleAlphaU8(img))
284    }
285}
286
287impl HasIntoDynIntensityMutImage<u16, SVec<u16, 2>> for MutImageR<u16, 2> {
288    fn into_dyn(img: Self) -> DynIntensityMutImage {
289        DynIntensityMutImage::GrayscaleAlphaU16(img)
290    }
291
292    fn try_into_dyn_u(img: Self) -> Option<DynIntensityMutImageU> {
293        Some(DynIntensityMutImageU::GrayscaleAlphaU16(img))
294    }
295}
296
297impl HasIntoDynIntensityMutImage<f32, SVec<f32, 2>> for MutImageR<f32, 2> {
298    fn into_dyn(img: Self) -> DynIntensityMutImage {
299        DynIntensityMutImage::GrayscaleAlphaF32(img)
300    }
301
302    fn try_into_dyn_u(_img: Self) -> Option<DynIntensityMutImageU> {
303        None
304    }
305}
306
307impl HasIntoDynIntensityMutImage<u8, SVec<u8, 3>> for MutImageR<u8, 3> {
308    fn into_dyn(img: Self) -> DynIntensityMutImage {
309        DynIntensityMutImage::RgbU8(img)
310    }
311
312    fn try_into_dyn_u(img: Self) -> Option<DynIntensityMutImageU> {
313        Some(DynIntensityMutImageU::RgbU8(img))
314    }
315}
316
317impl HasIntoDynIntensityMutImage<u16, SVec<u16, 3>> for MutImageR<u16, 3> {
318    fn into_dyn(img: Self) -> DynIntensityMutImage {
319        DynIntensityMutImage::RgbU16(img)
320    }
321
322    fn try_into_dyn_u(img: Self) -> Option<DynIntensityMutImageU> {
323        Some(DynIntensityMutImageU::RgbU16(img))
324    }
325}
326
327impl HasIntoDynIntensityMutImage<f32, SVec<f32, 3>> for MutImageR<f32, 3> {
328    fn into_dyn(img: Self) -> DynIntensityMutImage {
329        DynIntensityMutImage::RgbF32(img)
330    }
331
332    fn try_into_dyn_u(_img: Self) -> Option<DynIntensityMutImageU> {
333        None
334    }
335}
336
337impl HasIntoDynIntensityMutImage<u8, SVec<u8, 4>> for MutImageR<u8, 4> {
338    fn into_dyn(img: Self) -> DynIntensityMutImage {
339        DynIntensityMutImage::RgbaU8(img)
340    }
341
342    fn try_into_dyn_u(img: Self) -> Option<DynIntensityMutImageU> {
343        Some(DynIntensityMutImageU::RgbaU8(img))
344    }
345}
346
347impl HasIntoDynIntensityMutImage<u16, SVec<u16, 4>> for MutImageR<u16, 4> {
348    fn into_dyn(img: Self) -> DynIntensityMutImage {
349        DynIntensityMutImage::RgbaU16(img)
350    }
351
352    fn try_into_dyn_u(img: Self) -> Option<DynIntensityMutImageU> {
353        Some(DynIntensityMutImageU::RgbaU16(img))
354    }
355}
356
357impl HasIntoDynIntensityMutImage<f32, SVec<f32, 4>> for MutImageR<f32, 4> {
358    fn into_dyn(img: Self) -> DynIntensityMutImage {
359        DynIntensityMutImage::RgbaF32(img)
360    }
361
362    fn try_into_dyn_u(_img: Self) -> Option<DynIntensityMutImageU> {
363        None
364    }
365}