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>;