Skip to main content

bymsdfgen_core/
bitmap.rs

1//! Owning, channel-generic pixel buffer. Port of `core/Bitmap.h` + `BitmapRef.hpp`.
2//!
3//! Uses const generics for the channel count `N`, so `Bitmap<f32, 3>` and
4//! `Bitmap<f32, 1>` are distinct monomorphized types with no per-pixel branching.
5//! Access goes through bounds-checked slices instead of the original's raw pointer
6//! arithmetic — in release builds the checks vanish for in-range indices.
7//!
8//! Pixels are stored row-major with row `0` at the bottom (Y points upward, the
9//! msdfgen default). Output orientation is applied when saving.
10
11/// An owned `width × height` bitmap with `N` channels per pixel of type `T`.
12#[derive(Debug, Clone)]
13pub struct Bitmap<T, const N: usize> {
14    pub width: usize,
15    pub height: usize,
16    data: Vec<T>,
17}
18
19impl<T: Copy + Default, const N: usize> Bitmap<T, N> {
20    /// Allocate a zero-initialized bitmap.
21    pub fn new(width: usize, height: usize) -> Self {
22        Bitmap {
23            width,
24            height,
25            data: vec![T::default(); width * height * N],
26        }
27    }
28}
29
30impl<T, const N: usize> Bitmap<T, N> {
31    #[inline]
32    fn offset(&self, x: usize, y: usize) -> usize {
33        N * (self.width * y + x)
34    }
35
36    /// Immutable view of pixel `(x, y)` as an `N`-channel slice.
37    #[inline]
38    pub fn pixel(&self, x: usize, y: usize) -> &[T] {
39        let o = self.offset(x, y);
40        &self.data[o..o + N]
41    }
42
43    /// Mutable view of pixel `(x, y)` as an `N`-channel slice.
44    #[inline]
45    pub fn pixel_mut(&mut self, x: usize, y: usize) -> &mut [T] {
46        let o = self.offset(x, y);
47        &mut self.data[o..o + N]
48    }
49
50    /// The whole backing buffer (row-major, `N` channels interleaved).
51    #[inline]
52    pub fn data(&self) -> &[T] {
53        &self.data
54    }
55
56    #[inline]
57    pub fn data_mut(&mut self) -> &mut [T] {
58        &mut self.data
59    }
60
61    /// Iterate rows as `(y, row_slice)` where `row_slice` has `width*N` elements.
62    pub fn rows_mut(&mut self) -> impl Iterator<Item = (usize, &mut [T])> {
63        let stride = self.width * N;
64        self.data.chunks_mut(stride).enumerate()
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71
72    #[test]
73    fn alloc_and_access() {
74        let mut b: Bitmap<f32, 3> = Bitmap::new(4, 2);
75        assert_eq!(b.data().len(), 4 * 2 * 3);
76        b.pixel_mut(1, 1).copy_from_slice(&[0.1, 0.2, 0.3]);
77        assert_eq!(b.pixel(1, 1), &[0.1, 0.2, 0.3]);
78    }
79}