1#![no_std]
25
26#[cfg(feature = "std")]
27extern crate std;
28
29mod enums;
30mod error;
31
32pub use crate::{
33 enums::{ColorModel, ColorPrimaries, Format, SupercompressionScheme, TransferFunction},
34 error::ParseError,
35};
36
37use core::convert::TryInto;
38
39pub struct Reader<Data: AsRef<[u8]>> {
41 input: Data,
42}
43
44impl<Data: AsRef<[u8]>> Reader<Data> {
45 pub fn new(input: Data) -> Result<Self, ParseError> {
47 if input.as_ref().len() < Header::LENGTH {
48 return Err(ParseError::UnexpectedEnd);
49 }
50 if !input.as_ref().starts_with(&KTX2_MAGIC) {
51 return Err(ParseError::BadMagic);
52 }
53 let header_data = input.as_ref()[0..Header::LENGTH].try_into().unwrap();
54 let header = Header::from_bytes(header_data);
55 header.validate()?;
56
57 if (header.dfd_byte_offset + header.dfd_byte_length) as usize >= input.as_ref().len() {
58 return Err(ParseError::UnexpectedEnd);
59 }
60
61 let result = Self { input };
62 result.level_index()?; let trailing = result.level_index().unwrap().max_by_key(|l| l.offset).unwrap();
66 if trailing.offset + trailing.length_bytes > result.input.as_ref().len() as u64 {
67 return Err(ParseError::UnexpectedEnd);
68 }
69
70 Ok(result)
71 }
72
73 fn level_index(&self) -> ParseResult<impl ExactSizeIterator<Item = LevelIndex> + '_> {
74 let level_count = self.header().level_count.max(1) as usize;
75
76 let level_index_end_byte = Header::LENGTH + level_count * LevelIndex::LENGTH;
77 let level_index_bytes = self
78 .input
79 .as_ref()
80 .get(Header::LENGTH..level_index_end_byte)
81 .ok_or(ParseError::UnexpectedEnd)?;
82 Ok(level_index_bytes
83 .chunks_exact(LevelIndex::LENGTH)
84 .map(LevelIndex::from_bytes))
85 }
86
87 pub fn data(&self) -> &[u8] {
89 self.input.as_ref()
90 }
91
92 pub fn header(&self) -> Header {
94 let bytes = self.input.as_ref()[0..Header::LENGTH].try_into().unwrap();
95 Header::from_bytes(bytes)
96 }
97
98 pub fn levels(&self) -> impl ExactSizeIterator<Item = &[u8]> + '_ {
100 self.level_index()
101 .unwrap()
102 .map(move |level| &self.input.as_ref()[level.offset as usize..(level.offset + level.length_bytes) as usize])
103 }
104
105 pub fn supercompression_global_data(&self) -> &[u8] {
106 let header = self.header();
107 let start = header.sgd_byte_offset as usize;
108 let end = (header.sgd_byte_offset + header.sgd_byte_length) as usize;
109 &self.input.as_ref()[start..end]
110 }
111
112 pub fn data_format_descriptors(&self) -> impl Iterator<Item = DataFormatDescriptor> {
113 let header = self.header();
114 let start = header.dfd_byte_offset as usize;
115 let end = (header.dfd_byte_offset + header.dfd_byte_length) as usize;
116 DataFormatDescriptorIterator {
117 data: &self.input.as_ref()[start + 4..end],
119 }
120 }
121}
122
123struct DataFormatDescriptorIterator<'data> {
124 data: &'data [u8],
125}
126
127impl<'data> Iterator for DataFormatDescriptorIterator<'data> {
128 type Item = DataFormatDescriptor<'data>;
129
130 fn next(&mut self) -> Option<Self::Item> {
131 if self.data.len() < DataFormatDescriptorHeader::LENGTH {
132 return None;
133 }
134 DataFormatDescriptorHeader::parse(&self.data[..DataFormatDescriptorHeader::LENGTH]).map_or(
135 None,
136 |(header, descriptor_block_size)| {
137 if descriptor_block_size == 0 || self.data.len() < descriptor_block_size {
138 return None;
139 }
140 let data = &self.data[DataFormatDescriptorHeader::LENGTH..descriptor_block_size];
141 self.data = &self.data[descriptor_block_size..];
142 Some(DataFormatDescriptor { header, data })
143 },
144 )
145 }
146}
147
148const KTX2_MAGIC: [u8; 12] = [0xAB, 0x4B, 0x54, 0x58, 0x20, 0x32, 0x30, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A];
150
151type ParseResult<T> = Result<T, ParseError>;
153
154#[derive(Copy, Clone, Eq, PartialEq, Debug)]
156pub struct Header {
157 pub format: Option<Format>,
158 pub type_size: u32,
159 pub pixel_width: u32,
160 pub pixel_height: u32,
161 pub pixel_depth: u32,
162 pub layer_count: u32,
163 pub face_count: u32,
164 pub level_count: u32,
165 pub supercompression_scheme: Option<SupercompressionScheme>,
166 dfd_byte_offset: u32,
167 dfd_byte_length: u32,
168 kvd_byte_offset: u32,
169 kvd_byte_length: u32,
170 sgd_byte_offset: u64,
171 sgd_byte_length: u64,
172}
173
174impl Header {
175 const LENGTH: usize = 80;
176
177 fn from_bytes(data: &[u8; Self::LENGTH]) -> Self {
178 Self {
179 format: Format::new(u32::from_le_bytes(data[12..16].try_into().unwrap())),
180 type_size: u32::from_le_bytes(data[16..20].try_into().unwrap()),
181 pixel_width: u32::from_le_bytes(data[20..24].try_into().unwrap()),
182 pixel_height: u32::from_le_bytes(data[24..28].try_into().unwrap()),
183 pixel_depth: u32::from_le_bytes(data[28..32].try_into().unwrap()),
184 layer_count: u32::from_le_bytes(data[32..36].try_into().unwrap()),
185 face_count: u32::from_le_bytes(data[36..40].try_into().unwrap()),
186 level_count: u32::from_le_bytes(data[40..44].try_into().unwrap()),
187 supercompression_scheme: SupercompressionScheme::new(u32::from_le_bytes(data[44..48].try_into().unwrap())),
188 dfd_byte_offset: u32::from_le_bytes(data[48..52].try_into().unwrap()),
189 dfd_byte_length: u32::from_le_bytes(data[52..56].try_into().unwrap()),
190 kvd_byte_offset: u32::from_le_bytes(data[56..60].try_into().unwrap()),
191 kvd_byte_length: u32::from_le_bytes(data[60..64].try_into().unwrap()),
192 sgd_byte_offset: u64::from_le_bytes(data[64..72].try_into().unwrap()),
193 sgd_byte_length: u64::from_le_bytes(data[72..80].try_into().unwrap()),
194 }
195 }
196
197 fn validate(&self) -> ParseResult<()> {
198 if self.pixel_width == 0 {
199 return Err(ParseError::ZeroWidth);
200 }
201 if self.face_count == 0 {
202 return Err(ParseError::ZeroFaceCount);
203 }
204 Ok(())
205 }
206}
207
208#[derive(Debug, Eq, PartialEq, Copy, Clone)]
209struct LevelIndex {
210 offset: u64,
211 length_bytes: u64,
212 uncompressed_length_bytes: u64,
213}
214
215impl LevelIndex {
216 const LENGTH: usize = 24;
217
218 pub fn from_bytes(data: &[u8]) -> Self {
219 Self {
220 offset: u64::from_le_bytes(data[0..8].try_into().unwrap()),
221 length_bytes: u64::from_le_bytes(data[8..16].try_into().unwrap()),
222 uncompressed_length_bytes: u64::from_le_bytes(data[16..24].try_into().unwrap()),
223 }
224 }
225}
226
227bitflags::bitflags! {
228 #[repr(transparent)]
229 pub struct ChannelTypeQualifiers: u32 {
230 const LINEAR = (1 << 0);
231 const EXPONENT = (1 << 1);
232 const SIGNED = (1 << 2);
233 const FLOAT = (1 << 3);
234 }
235}
236
237bitflags::bitflags! {
238 #[derive(Default)]
239 #[repr(transparent)]
240 pub struct DataFormatFlags: u32 {
241 const STRAIGHT_ALPHA = 0;
242 const ALPHA_PREMULTIPLIED = (1 << 0);
243 }
244}
245
246#[derive(Debug, PartialEq, Eq)]
247pub struct DataFormatDescriptorHeader {
248 pub vendor_id: u32, pub descriptor_type: u32, pub version_number: u32, }
252
253impl DataFormatDescriptorHeader {
254 const LENGTH: usize = 8;
255
256 pub const BASIC: Self = Self {
257 vendor_id: 0,
258 descriptor_type: 0,
259 version_number: 2,
260 };
261
262 fn parse(bytes: &[u8]) -> Result<(Self, usize), ParseError> {
263 let mut offset = 0;
264
265 let v = bytes_to_u32(bytes, &mut offset)?;
266 let vendor_id = shift_and_mask_lower(0, 17, v);
267 let descriptor_type = shift_and_mask_lower(17, 15, v);
268
269 let v = bytes_to_u32(bytes, &mut offset)?;
270 let version_number = shift_and_mask_lower(0, 16, v);
271 let descriptor_block_size = shift_and_mask_lower(16, 16, v);
272
273 Ok((
274 Self {
275 vendor_id,
276 descriptor_type,
277 version_number,
278 },
279 descriptor_block_size as usize,
280 ))
281 }
282}
283
284pub struct DataFormatDescriptor<'data> {
285 pub header: DataFormatDescriptorHeader,
286 pub data: &'data [u8],
287}
288
289pub struct BasicDataFormatDescriptor<'data> {
290 pub color_model: Option<ColorModel>, pub color_primaries: Option<ColorPrimaries>, pub transfer_function: Option<TransferFunction>, pub flags: DataFormatFlags, pub texel_block_dimensions: [u32; 4], pub bytes_planes: [u32; 8], sample_data: &'data [u8],
300}
301
302impl<'data> BasicDataFormatDescriptor<'data> {
303 pub fn parse(bytes: &'data [u8]) -> Result<Self, ParseError> {
304 let mut offset = 0;
305
306 let v = bytes_to_u32(bytes, &mut offset)?;
307 let model = shift_and_mask_lower(0, 8, v);
308 let primaries = shift_and_mask_lower(8, 8, v);
309 let transfer = shift_and_mask_lower(16, 8, v);
310 let flags = shift_and_mask_lower(24, 8, v);
311
312 let v = bytes_to_u32(bytes, &mut offset)?;
313 let texel_block_dimensions = [
314 shift_and_mask_lower(0, 8, v) + 1,
315 shift_and_mask_lower(8, 8, v) + 1,
316 shift_and_mask_lower(16, 8, v) + 1,
317 shift_and_mask_lower(24, 8, v) + 1,
318 ];
319
320 let v = bytes_to_u32(bytes, &mut offset)?;
321 let mut bytes_planes = [0u32; 8];
322 bytes_planes[0] = shift_and_mask_lower(0, 8, v);
323 bytes_planes[1] = shift_and_mask_lower(8, 8, v);
324 bytes_planes[2] = shift_and_mask_lower(16, 8, v);
325 bytes_planes[3] = shift_and_mask_lower(24, 8, v);
326
327 let v = bytes_to_u32(bytes, &mut offset)?;
328 bytes_planes[4] = shift_and_mask_lower(0, 8, v);
329 bytes_planes[5] = shift_and_mask_lower(8, 8, v);
330 bytes_planes[6] = shift_and_mask_lower(16, 8, v);
331 bytes_planes[7] = shift_and_mask_lower(24, 8, v);
332
333 Ok(Self {
334 color_model: ColorModel::new(model),
335 color_primaries: ColorPrimaries::new(primaries),
336 transfer_function: TransferFunction::new(transfer),
337 flags: DataFormatFlags::from_bits_truncate(flags),
338 texel_block_dimensions,
339 bytes_planes,
340 sample_data: &bytes[offset..],
341 })
342 }
343
344 pub fn sample_information(&self) -> impl Iterator<Item = SampleInformation> + 'data {
345 SampleInformationIterator { data: self.sample_data }
346 }
347}
348
349struct SampleInformationIterator<'data> {
350 data: &'data [u8],
351}
352
353impl<'data> Iterator for SampleInformationIterator<'data> {
354 type Item = SampleInformation;
355
356 fn next(&mut self) -> Option<Self::Item> {
357 if self.data.len() < SampleInformation::LENGTH {
358 return None;
359 }
360 SampleInformation::parse(&self.data[..SampleInformation::LENGTH]).map_or(None, |sample_information| {
361 self.data = &self.data[SampleInformation::LENGTH..];
362 Some(sample_information)
363 })
364 }
365}
366
367#[derive(Debug)]
368pub struct SampleInformation {
369 pub bit_offset: u32, pub bit_length: u32, pub channel_type: u32, pub channel_type_qualifiers: ChannelTypeQualifiers, pub sample_positions: [u32; 4], pub lower: u32, pub upper: u32, }
377
378impl SampleInformation {
379 const LENGTH: usize = 16;
380
381 fn parse(bytes: &[u8]) -> Result<Self, ParseError> {
382 let mut offset = 0;
383
384 let v = bytes_to_u32(bytes, &mut offset)?;
385 let bit_offset = shift_and_mask_lower(0, 16, v);
386 let bit_length = shift_and_mask_lower(16, 8, v) + 1;
387 let channel_type = shift_and_mask_lower(24, 4, v);
388 let channel_type_qualifiers = ChannelTypeQualifiers::from_bits_truncate(shift_and_mask_lower(28, 4, v));
389
390 let v = bytes_to_u32(bytes, &mut offset)?;
391 let sample_positions = [
392 shift_and_mask_lower(0, 8, v),
393 shift_and_mask_lower(8, 8, v),
394 shift_and_mask_lower(16, 8, v),
395 shift_and_mask_lower(24, 8, v),
396 ];
397 let lower = bytes_to_u32(bytes, &mut offset)?;
398 let upper = bytes_to_u32(bytes, &mut offset)?;
399
400 Ok(Self {
401 bit_offset,
402 bit_length,
403 channel_type,
404 channel_type_qualifiers,
405 sample_positions,
406 lower,
407 upper,
408 })
409 }
410}
411
412fn bytes_to_u32(bytes: &[u8], offset: &mut usize) -> Result<u32, ParseError> {
413 let v = u32::from_le_bytes(
414 bytes
415 .get(*offset..*offset + 4)
416 .ok_or(ParseError::UnexpectedEnd)?
417 .try_into()
418 .unwrap(),
419 );
420 *offset += 4;
421 Ok(v)
422}
423
424fn shift_and_mask_lower(shift: u32, mask: u32, value: u32) -> u32 {
425 (value >> shift) & ((1 << mask) - 1)
426}