Skip to main content

ctt_intel_texture_compressor/
lib.rs

1#[cfg(feature = "prebuilt")]
2extern crate ctt_intel_texture_compressor_prebuilt;
3
4pub mod bindings;
5
6pub mod astc;
7pub mod bc1;
8pub mod bc3;
9pub mod bc4;
10pub mod bc5;
11pub mod bc6h;
12pub mod bc7;
13pub mod etc1;
14
15/// Describes a 2D image to block-compress.
16///
17/// `COMPONENTS` is the number of **bytes per pixel** in the source data. This
18/// determines the expected tightly-packed stride (`width * COMPONENTS`) and is
19/// used to validate that `data` is large enough. The actual channel layout
20/// depends on which encoder consumes the surface — see the individual format
21/// modules for details.
22///
23/// # Available surface type aliases
24///
25/// | Alias | `COMPONENTS` | Layout | Used by |
26/// |---|---|---|---|
27/// | [`RSurface`] | 1 | `R8` (1 byte/pixel) | [`bc4`] |
28/// | [`RgSurface`] | 2 | `R8 G8` interleaved (2 bytes/pixel) | [`bc5`] |
29/// | [`RgbaSurface`] | 4 | `R8 G8 B8 A8` interleaved (4 bytes/pixel) | [`bc1`], [`bc3`], [`bc7`], [`astc`], [`etc1`] |
30/// | [`Rgba16Surface`] | 8 | `R16 G16 B16 A16` interleaved (8 bytes/pixel) | [`bc6h`] |
31#[derive(Debug, Copy, Clone)]
32pub struct Surface<'a, const COMPONENTS: usize> {
33    /// The raw pixel data for the image.
34    ///
35    /// The byte interpretation depends on the encoder that consumes this
36    /// surface. For most formats, each byte is one u8 channel sample. For
37    /// [`bc6h`], every two bytes form a little-endian u16 channel sample.
38    ///
39    /// The data does not need to be tightly packed, but if it isn't, `stride`
40    /// must differ from `width * COMPONENTS`.
41    ///
42    /// Expected to be at least `stride * height` bytes.
43    pub data: &'a [u8],
44    /// The width of the image in texels.
45    pub width: u32,
46    /// The height of the image in texels.
47    pub height: u32,
48    /// The stride between rows of the image, in bytes.
49    ///
50    /// For tightly-packed data this is `width * COMPONENTS`.
51    pub stride: u32,
52}
53
54impl<'a, const COMPONENTS: usize> Surface<'a, COMPONENTS> {
55    /// Creates a new surface, validating that dimensions fit within `i32` (required
56    /// by the underlying C API) and that `data` is large enough for the given
57    /// stride and height.
58    ///
59    /// # Panics
60    ///
61    /// Panics if `width`, `height`, or `stride` exceed `i32::MAX`, or if
62    /// `data.len()` is less than `stride * height`.
63    pub fn new(data: &'a [u8], width: u32, height: u32, stride: u32) -> Self {
64        assert!(
65            i32::try_from(width).is_ok(),
66            "width {width} exceeds i32::MAX"
67        );
68        assert!(
69            i32::try_from(height).is_ok(),
70            "height {height} exceeds i32::MAX"
71        );
72        assert!(
73            i32::try_from(stride).is_ok(),
74            "stride {stride} exceeds i32::MAX"
75        );
76        let width_components = (width as usize)
77            .checked_mul(COMPONENTS)
78            .expect("width * COMPONENTS overflows usize");
79        assert!(
80            stride as usize >= width_components,
81            "stride {stride} is less than width * COMPONENTS ({} * {COMPONENTS} = {width_components})",
82            width,
83        );
84        let required = (stride as usize)
85            .checked_mul(height as usize)
86            .expect("stride * height overflows usize");
87        assert!(
88            data.len() >= required,
89            "data length {} is less than stride * height ({required})",
90            data.len()
91        );
92        Self {
93            data,
94            width,
95            height,
96            stride,
97        }
98    }
99}
100
101/// 4-channel, 8-bit surface: `R8 G8 B8 A8` — 4 bytes per pixel.
102///
103/// Used by [`bc1`], [`bc3`], [`bc7`], [`astc`], and [`etc1`].
104pub type RgbaSurface<'a> = Surface<'a, 4>;
105
106/// 2-channel, 8-bit surface: `R8 G8` interleaved — 2 bytes per pixel.
107///
108/// Used by [`bc5`].
109pub type RgSurface<'a> = Surface<'a, 2>;
110
111/// 1-channel, 8-bit surface: `R8` — 1 byte per pixel.
112///
113/// Used by [`bc4`].
114pub type RSurface<'a> = Surface<'a, 1>;
115
116/// 4-channel, 16-bit surface: `R16 G16 B16 A16` — 8 bytes per pixel.
117///
118/// Each channel is a little-endian unsigned 16-bit integer (u16) in the range
119/// `0..=65535`. The alpha channel is present in the layout but ignored by
120/// [`bc6h`].
121pub type Rgba16Surface<'a> = Surface<'a, 8>;