Skip to main content

basis_universal/encoding/
compressor_image.rs

1use basis_universal_sys as sys;
2pub use basis_universal_sys::ColorU8;
3
4// foreign_types::foreign_type! {
5//     /// A Foo.
6//     pub unsafe type Foo
7//         : Sync + Send // optional
8//     {
9//         type CType = sys::basisu_image;
10//         fn drop = unimplemented!();
11//     }
12// }
13
14/// A reference to an image being stored by [CompressorParams](super::CompressorParams). Generally
15/// used to insert the source data that is to be encoded by a [Compressor](super::Compressor).
16pub struct CompressorImageRef(pub *mut sys::basisu_image);
17
18impl CompressorImageRef {
19    /// Sets the image to be completely empty (i.e. 0 width, 0 height). (This was called `clear` in
20    /// the upstream API.)
21    pub fn invalidate(&mut self) {
22        unsafe {
23            sys::image_clear(self.0);
24        }
25    }
26
27    /// Resizes the image to the given width/height
28    ///
29    /// By default the pitch will be equal to the width. To customize this, use `resize_with_pitch`
30    pub fn resize(
31        &mut self,
32        width: u32,
33        height: u32,
34    ) {
35        unsafe {
36            sys::image_resize(self.0, width, height);
37        }
38    }
39
40    /// Resize the image to the given width/height with a custom "pitch". The pitch is the
41    /// offset between rows and is not needed for all formats. By default, the pitch will be equal
42    /// to the width
43    pub fn resize_with_pitch(
44        &mut self,
45        width: u32,
46        height: u32,
47        pitch: u32,
48    ) {
49        unsafe {
50            sys::image_resize_with_pitch(self.0, width, height, pitch);
51        }
52    }
53
54    /// Resize the image and populate it with the given data.
55    ///
56    /// channel_count should be the number of channels in the image (so >=1 and <= 4)
57    pub fn init(
58        &mut self,
59        data: &[u8],
60        width: u32,
61        height: u32,
62        channel_count: u8,
63    ) {
64        unsafe {
65            sys::image_init(self.0, data.as_ptr(), width, height, channel_count as _);
66        }
67    }
68
69    /// Returns the pixel value at a given x,y
70    pub fn pixel_at(
71        &self,
72        width: u32,
73        height: u32,
74    ) -> Option<ColorU8> {
75        unsafe {
76            let mut color = ColorU8 { combined: 0 };
77
78            if sys::image_get_pixel_at_checked(self.0, width, height, &mut color as *mut _) {
79                Some(color)
80            } else {
81                None
82            }
83        }
84    }
85
86    /// Returns teh pixel value at a given x,y without doing bounds checking
87    ///
88    /// # Safety
89    ///
90    /// Accessing pixel out of bounds of the image will result in undefined behavior
91    pub unsafe fn pixel_at_unchecked(
92        &self,
93        width: u32,
94        height: u32,
95    ) -> ColorU8 {
96        sys::image_get_pixel_at_unchecked(self.0, width, height)
97    }
98
99    /// Returns the width of the image in pixels
100    pub fn width(&self) -> u32 {
101        unsafe { sys::image_get_width(self.0) }
102    }
103
104    /// Returns the height of the image in pixels
105    pub fn height(&self) -> u32 {
106        unsafe { sys::image_get_height(self.0) }
107    }
108
109    /// Returns the pitch of the image in pixels, which represents the offset between rows
110    pub fn pitch(&self) -> u32 {
111        unsafe { sys::image_get_pitch(self.0) }
112    }
113
114    /// Returns the total number of pixels in the image
115    pub fn total_pixels(&self) -> u32 {
116        unsafe { sys::image_get_total_pixels(self.0) }
117    }
118
119    /// Returns how many blocks wide the image is, given `w`, the width of a block in pixels
120    pub fn block_width(
121        &self,
122        w: u32,
123    ) -> u32 {
124        unsafe { sys::image_get_block_width(self.0, w) }
125    }
126
127    /// Returns how many blocks high the image is, given `h`, the height of a block in pixels
128    pub fn block_height(
129        &self,
130        h: u32,
131    ) -> u32 {
132        unsafe { sys::image_get_block_height(self.0, h) }
133    }
134
135    /// Returns the number of blocks required to store the image, given `w` and `h`, the width and
136    /// height of a block in pixels
137    pub fn total_blocks(
138        &self,
139        w: u32,
140        h: u32,
141    ) -> u32 {
142        unsafe { sys::image_get_total_blocks(self.0, w, h) }
143    }
144
145    /// Returns a mutable reference to the pixel data as a slice of [ColorU8]
146    pub fn pixel_data_mut(&mut self) -> &mut [ColorU8] {
147        unsafe {
148            let data = sys::image_get_pixel_data(self.0);
149            std::slice::from_raw_parts_mut(data.pData, data.length as usize)
150        }
151    }
152
153    /// Returns a mutable reference to the pixel data as a slice of u8
154    pub fn pixel_data_u8_mut(&mut self) -> &mut [u8] {
155        unsafe {
156            let data = sys::image_get_pixel_data(self.0);
157            std::slice::from_raw_parts_mut(
158                data.pData as *mut u8,
159                data.length as usize * std::mem::size_of::<ColorU8>(),
160            )
161        }
162    }
163
164    /// Returns a mutable reference to the pixel data as a slice of u32
165    pub fn pixel_data_u32_mut(&mut self) -> &mut [u32] {
166        debug_assert_eq!(std::mem::size_of::<u32>(), std::mem::size_of::<ColorU8>());
167        unsafe {
168            let data = sys::image_get_pixel_data(self.0);
169            std::slice::from_raw_parts_mut(data.pData as *mut u32, data.length as usize)
170        }
171    }
172}