jxl_bitstream/container.rs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
pub mod box_header;
pub mod parse;
use box_header::*;
pub use parse::ParseEvent;
use parse::*;
/// Wrapper that detects container format from underlying reader.
#[derive(Debug, Default)]
pub struct ContainerDetectingReader {
state: DetectState,
jxlp_index_state: JxlpIndexState,
previous_consumed_bytes: usize,
}
#[derive(Debug, Default)]
enum DetectState {
#[default]
WaitingSignature,
WaitingBoxHeader,
WaitingJxlpIndex(ContainerBoxHeader),
InAuxBox {
#[allow(unused)]
header: ContainerBoxHeader,
bytes_left: Option<usize>,
},
InCodestream {
kind: BitstreamKind,
bytes_left: Option<usize>,
},
}
/// Structure of the decoded bitstream.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum BitstreamKind {
/// Decoder can't determine structure of the bitstream.
Unknown,
/// Bitstream is a direct JPEG XL codestream without box structure.
BareCodestream,
/// Bitstream is a JPEG XL container with box structure.
Container,
/// Bitstream is not a valid JPEG XL image.
Invalid,
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
enum JxlpIndexState {
#[default]
Initial,
SingleJxlc,
Jxlp(u32),
JxlpFinished,
}
impl ContainerDetectingReader {
pub fn new() -> Self {
Self::default()
}
pub fn kind(&self) -> BitstreamKind {
match self.state {
DetectState::WaitingSignature => BitstreamKind::Unknown,
DetectState::WaitingBoxHeader
| DetectState::WaitingJxlpIndex(..)
| DetectState::InAuxBox { .. } => BitstreamKind::Container,
DetectState::InCodestream { kind, .. } => kind,
}
}
/// Feeds bytes to the parser, and receives parser events.
///
/// The parser might not consume all of the buffer. Use [`previous_consumed_bytes`] to get how
/// many bytes are consumed. Bytes not consumed by the parser should be fed into the parser
/// again.
///
/// [`previous_consumed_bytes`]: ContainerDetectingReader::previous_consumed_bytes
pub fn feed_bytes<'inner, 'buf>(
&'inner mut self,
input: &'buf [u8],
) -> ParseEvents<'inner, 'buf> {
ParseEvents::new(self, input)
}
/// Get how many bytes are consumed by the previous call to [`feed_bytes`].
///
/// Bytes not consumed by the parser should be fed into the parser again.
///
/// [`feed_bytes`]: ContainerDetectingReader::feed_bytes
pub fn previous_consumed_bytes(&self) -> usize {
self.previous_consumed_bytes
}
}