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#[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 #[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 #[inline]
50 #[must_use]
51 pub fn single_raw(&self) -> Option<Vec<UVec2>> {
52 self.iter().next()
53 }
54
55 #[inline]
61 #[must_use]
62 pub fn multi_translated(&self) -> Vec<Vec<Vec2>> {
63 self.anchor().translate_polygons(self.iter())
64 }
65
66 #[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}