Skip to main content

firefly_rust/graphics/
image.rs

1use crate::*;
2
3/// A loaded image file.
4///
5/// Can be loaded as [`FileBuf`] from ROM with [`load_file_buf`]
6/// and then cast using [`Into`].
7pub struct Image<'a> {
8    pub(crate) raw: &'a [u8],
9}
10
11impl<'a> From<File<'a>> for Image<'a> {
12    fn from(value: File<'a>) -> Self {
13        Self { raw: value.raw }
14    }
15}
16
17#[cfg(feature = "alloc")]
18impl<'a> From<&'a FileBuf> for Image<'a> {
19    fn from(value: &'a FileBuf) -> Self {
20        Self { raw: &value.raw }
21    }
22}
23
24impl<'a> From<Canvas<'a>> for Image<'a> {
25    fn from(value: Canvas<'a>) -> Self {
26        Self { raw: value.raw }
27    }
28}
29
30#[cfg(feature = "alloc")]
31impl<'a> From<&'a CanvasBuf> for Image<'a> {
32    fn from(value: &'a CanvasBuf) -> Self {
33        Self { raw: &value.raw }
34    }
35}
36
37impl<'a> Image<'a> {
38    /// Reinterpret raw bytes as an image.
39    ///
40    /// # Safety
41    ///
42    /// Using this function requires a good understanding of the internal
43    /// Firefly Zero binary image format. In 99% cases, you should not construct
44    /// a raw image but instead load it from a [`File`] or generate using [`Canvas`].
45    #[must_use]
46    pub const unsafe fn from_bytes(raw: &'a [u8]) -> Self {
47        Self { raw }
48    }
49
50    /// Get a rectangle subregion of the image.
51    #[must_use]
52    pub const fn sub(&self, p: Point, s: Size) -> SubImage<'a> {
53        SubImage {
54            point: p,
55            size: s,
56            raw: self.raw,
57        }
58    }
59
60    /// The color used for transparency. If no transparency, returns [`Color::None`].
61    #[must_use]
62    pub fn transparency(&self) -> Color {
63        Color::from(self.raw[3] + 1)
64    }
65
66    /// The number of pixels the image has.
67    #[must_use]
68    pub const fn pixels(&self) -> usize {
69        const HEADER_SIZE: usize = 4;
70        const PPB: usize = 2;
71        (self.raw.len() - HEADER_SIZE) * PPB
72    }
73
74    /// The image width in pixels.
75    #[must_use]
76    pub fn width(&self) -> u16 {
77        let big = u16::from(self.raw[1]);
78        let little = u16::from(self.raw[2]);
79        big | (little << 8)
80    }
81
82    /// The image height in pixels.
83    #[must_use]
84    pub fn height(&self) -> u16 {
85        let p = self.pixels();
86        let w = usize::from(self.width());
87        p.checked_div(w).unwrap_or(0) as u16
88    }
89
90    /// The image size in pixels.
91    #[must_use]
92    pub fn size(&self) -> Size {
93        Size {
94            width: i32::from(self.width()),
95            height: i32::from(self.height()),
96        }
97    }
98}
99
100/// A subregion of an image. Constructed using [`Image::sub`].
101pub struct SubImage<'a> {
102    pub(crate) point: Point,
103    pub(crate) size: Size,
104    pub(crate) raw: &'a [u8],
105}