1use crate::pixmap::Pixmap;
7use alloc::sync::Arc;
8
9#[derive(Debug, Clone, PartialEq, Eq)]
11pub struct Mask {
12 data: Arc<[u8]>,
13 width: u16,
14 height: u16,
15}
16
17impl Mask {
18 pub fn new_alpha(pixmap: &Pixmap) -> Self {
20 Self::new_with(pixmap, true)
21 }
22
23 pub fn new_luminance(pixmap: &Pixmap) -> Self {
25 Self::new_with(pixmap, false)
26 }
27
28 fn new_with(pixmap: &Pixmap, alpha_mask: bool) -> Self {
29 let data = Arc::from_iter(pixmap.data().iter().map(|pixel| {
30 if alpha_mask {
31 pixel.a
32 } else {
33 let r = f32::from(pixel.r) / 255.;
34 let g = f32::from(pixel.g) / 255.;
35 let b = f32::from(pixel.b) / 255.;
36
37 let luma = r * 0.2126 + g * 0.7152 + b * 0.0722;
43 #[expect(clippy::cast_possible_truncation, reason = "This cannot overflow")]
44 {
45 (luma * 255.0 + 0.5) as u8
46 }
47 }
48 }));
49
50 Self {
51 data,
52 width: pixmap.width(),
53 height: pixmap.height(),
54 }
55 }
56
57 pub fn width(&self) -> u16 {
59 self.width
60 }
61
62 pub fn height(&self) -> u16 {
64 self.height
65 }
66
67 pub fn sample(&self, x: u16, y: u16) -> u8 {
72 debug_assert!(
73 x < self.width && y < self.height,
74 "cannot sample mask outside of its range"
75 );
76
77 self.data[y as usize * self.width as usize + x as usize]
78 }
79}