edges/
lib.rs

1#![doc = include_str!("../README.md")]
2
3use binary_image::{BinaryImage, BinaryView, Bit};
4use image::{DynamicImage, GenericImageView};
5
6#[cfg(feature = "bevy")]
7pub(crate) use bevy_math::prelude::{UVec2, Vec2};
8#[cfg(all(not(feature = "bevy"), feature = "glam-latest"))]
9pub(crate) use glam::{UVec2, Vec2};
10
11pub extern crate binary_image;
12pub use iter::Edges as EdgesIter;
13
14pub mod anchor;
15pub mod utils;
16
17#[cfg(feature = "bevy")]
18mod bevy;
19mod iter;
20#[cfg(all(feature = "bevy", test))]
21mod tests;
22
23/// A struct representing the edges of a image.
24#[derive(Default, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
25pub struct Edges<I: GenericImageView<Pixel = Bit>>(pub I);
26
27impl<I> Edges<I>
28where
29    I: GenericImageView<Pixel = Bit>,
30{
31    /// Translates the edges of a single image into a coordinate system centered at (0, 0).
32    ///
33    /// # Returns
34    ///
35    /// A vector of `Vec2` representing the translated edge points.
36    #[inline]
37    #[must_use]
38    pub fn single_translated(&self) -> Option<Vec<Vec2>> {
39        self.iter()
40            .next()
41            .map(|polygon| self.anchor().translate(polygon))
42    }
43
44    /// Retrieves the raw edge points of a single image.
45    ///
46    /// # Returns
47    ///
48    /// A vector of `UVec2` representing the raw edge points.
49    #[inline]
50    #[must_use]
51    pub fn single_raw(&self) -> Option<Vec<UVec2>> {
52        self.iter().next()
53    }
54
55    /// Translates the edges of multiple images into a coordinate system centered at (0, 0).
56    ///
57    /// # Returns
58    ///
59    /// A vector of vectors of `Vec2` representing the translated edge points of each image.
60    #[inline]
61    #[must_use]
62    pub fn multi_translated(&self) -> Vec<Vec<Vec2>> {
63        self.anchor().translate_polygons(self.iter())
64    }
65
66    /// Retrieves the raw edge points of multiple images.
67    ///
68    /// # Returns
69    ///
70    /// A vector of vectors of `UVec2` representing the raw edge points of each image.
71    #[inline]
72    #[must_use]
73    pub fn multi_raw(&self) -> Vec<Vec<UVec2>> {
74        self.iter().collect()
75    }
76
77    #[inline]
78    #[must_use]
79    pub fn iter(&self) -> iter::Edges<I> {
80        self.into_iter()
81    }
82
83    #[inline]
84    #[must_use]
85    fn anchor(&self) -> anchor::Anchor {
86        anchor::Anchor::Center(self.height(), self.width())
87    }
88}
89
90impl From<DynamicImage> for Edges<BinaryImage> {
91    fn from(image: DynamicImage) -> Edges<BinaryImage> {
92        Self(BinaryImage::from(image))
93    }
94}
95
96impl<'a> From<&'a DynamicImage> for Edges<BinaryView<'a, DynamicImage>> {
97    fn from(image: &'a DynamicImage) -> Edges<BinaryView<'a, DynamicImage>> {
98        Self(BinaryView::Ref(image))
99    }
100}
101
102impl<I> std::fmt::Debug for Edges<I>
103where
104    I: GenericImageView<Pixel = Bit>,
105{
106    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107        f.debug_struct("Edges")
108            .field("raw", &self.multi_raw())
109            .field("translated", &self.multi_translated())
110            .finish()
111    }
112}
113
114impl<I> std::ops::Deref for Edges<I>
115where
116    I: GenericImageView<Pixel = Bit>,
117{
118    type Target = I;
119    fn deref(&self) -> &Self::Target {
120        &self.0
121    }
122}
123
124impl<'a, I> IntoIterator for &'a Edges<I>
125where
126    I: GenericImageView<Pixel = Bit>,
127{
128    type Item = Vec<UVec2>;
129    type IntoIter = iter::Edges<'a, I>;
130    fn into_iter(self) -> Self::IntoIter {
131        Self::IntoIter::new(&self.0)
132    }
133}