1use bytemuck::{Pod, Zeroable};
5use hayro_interpret::color::AlphaColor;
6use image::codecs::png::PngEncoder;
7use image::{ExtendedColorType, ImageEncoder};
8use std::io::Cursor;
9use std::vec;
10use std::vec::Vec;
11
12#[derive(Clone, Copy, PartialEq, Eq, Debug, Pod, Zeroable)]
13#[repr(C)]
14pub(crate) struct PremulRgba8 {
15 pub r: u8,
17 pub g: u8,
19 pub b: u8,
21 pub a: u8,
23}
24
25impl PremulRgba8 {
26 #[must_use]
27 pub(crate) const fn from_u8_array([r, g, b, a]: [u8; 4]) -> Self {
28 Self { r, g, b, a }
29 }
30
31 #[must_use]
32 pub(crate) const fn from_u32(packed_bytes: u32) -> Self {
33 Self::from_u8_array(u32::to_ne_bytes(packed_bytes))
34 }
35}
36
37#[derive(Clone, Copy, PartialEq, Eq, Debug, Pod, Zeroable)]
38#[repr(C)]
39pub(crate) struct Rgba8 {
40 pub r: u8,
41 pub g: u8,
42 pub b: u8,
43 pub a: u8,
44}
45
46impl From<Rgba8> for AlphaColor {
47 fn from(value: Rgba8) -> Self {
48 Self::from_rgba8(value.r, value.g, value.b, value.a)
49 }
50}
51
52#[derive(Debug, Clone)]
54pub struct Pixmap {
55 width: u16,
57 height: u16,
59 buf: Vec<PremulRgba8>,
61}
62
63impl Pixmap {
64 pub(crate) fn new(width: u16, height: u16) -> Self {
66 let buf = vec![PremulRgba8::from_u32(0); width as usize * height as usize];
67 Self { width, height, buf }
68 }
69
70 pub fn width(&self) -> u16 {
72 self.width
73 }
74
75 pub fn height(&self) -> u16 {
77 self.height
78 }
79
80 pub(crate) fn data(&self) -> &[PremulRgba8] {
84 &self.buf
85 }
86
87 pub fn data_as_u8_slice(&self) -> &[u8] {
92 bytemuck::cast_slice(&self.buf)
93 }
94
95 pub fn data_as_u8_slice_mut(&mut self) -> &mut [u8] {
100 bytemuck::cast_slice_mut(&mut self.buf)
101 }
102
103 pub fn take_u8(self) -> Vec<u8> {
107 bytemuck::cast_vec(self.buf)
108 }
109
110 pub fn take_png(self) -> Vec<u8> {
112 let mut png_data = Vec::new();
113 let cursor = Cursor::new(&mut png_data);
114 let encoder = PngEncoder::new(cursor);
115 encoder
116 .write_image(
117 self.data_as_u8_slice(),
118 self.width() as u32,
119 self.height() as u32,
120 ExtendedColorType::Rgba8,
121 )
122 .expect("Failed to encode image");
123
124 png_data
125 }
126}