aboutsummaryrefslogtreecommitdiff
path: root/vendor/gif/src/reader/decoder.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gif/src/reader/decoder.rs')
-rw-r--r--vendor/gif/src/reader/decoder.rs724
1 files changed, 0 insertions, 724 deletions
diff --git a/vendor/gif/src/reader/decoder.rs b/vendor/gif/src/reader/decoder.rs
deleted file mode 100644
index f0f8eea..0000000
--- a/vendor/gif/src/reader/decoder.rs
+++ /dev/null
@@ -1,724 +0,0 @@
-use std::cmp;
-use std::error;
-use std::fmt;
-use std::io;
-use std::mem;
-use std::default::Default;
-
-use crate::common::{AnyExtension, Block, DisposalMethod, Extension, Frame};
-use crate::reader::DecodeOptions;
-
-use weezl::{BitOrder, decode::Decoder as LzwDecoder, LzwStatus};
-
-/// GIF palettes are RGB
-pub const PLTE_CHANNELS: usize = 3;
-
-/// An error returned in the case of the image not being formatted properly.
-#[derive(Debug)]
-pub struct DecodingFormatError {
- underlying: Box<dyn error::Error + Send + Sync + 'static>
-}
-
-impl fmt::Display for DecodingFormatError {
- fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
- fmt::Display::fmt(&*self.underlying, fmt)
- }
-}
-
-impl error::Error for DecodingFormatError {
- fn source(&self) -> Option<&(dyn error::Error + 'static)> {
- Some(&*self.underlying as _)
- }
-}
-
-impl DecodingFormatError {
- fn new(
- err: impl Into<Box<dyn error::Error + Send + Sync>>,
- ) -> Self {
- DecodingFormatError {
- underlying: err.into(),
- }
- }
-}
-
-#[derive(Debug)]
-/// Decoding error.
-pub enum DecodingError {
- /// Returned if the image is found to be malformed.
- Format(DecodingFormatError),
- /// Wraps `std::io::Error`.
- Io(io::Error),
-}
-
-impl DecodingError {
- #[inline]
- pub(crate) fn format(
- err: impl Into<Box<dyn error::Error + Send + Sync>>,
- ) -> Self {
- DecodingError::Format(DecodingFormatError::new(err))
- }
-}
-
-impl fmt::Display for DecodingError {
- fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
- match *self {
- DecodingError::Format(ref d) => d.fmt(fmt),
- DecodingError::Io(ref err) => err.fmt(fmt),
- }
- }
-}
-
-impl error::Error for DecodingError {
- fn source(&self) -> Option<&(dyn error::Error + 'static)> {
- match *self {
- DecodingError::Format(ref err) => Some(err),
- DecodingError::Io(ref err) => Some(err),
- }
- }
-}
-
-impl From<io::Error> for DecodingError {
- fn from(err: io::Error) -> Self {
- DecodingError::Io(err)
- }
-}
-
-impl From<DecodingFormatError> for DecodingError {
- fn from(err: DecodingFormatError) -> Self {
- DecodingError::Format(err)
- }
-}
-
-/// Configures how extensions should be handled
-#[derive(PartialEq, Debug)]
-pub enum Extensions {
- /// Saves all extention data
- Save,
- /// Skips the data of unknown extensions
- /// and extracts the data from known ones
- Skip
-}
-
-/// Indicates whether a certain object has been decoded
-#[derive(Debug)]
-pub enum Decoded<'a> {
- /// Decoded nothing.
- Nothing,
- /// Global palette.
- GlobalPalette(Vec<u8>),
- /// Index of the background color in the global palette.
- BackgroundColor(u8),
- /// Decoded the image trailer.
- Trailer,
- /// The start of a block.
- BlockStart(Block),
- /// Decoded a sub-block. More sub-block are available.
- ///
- /// Indicates the label of the extension which might be unknown. A label of `0` is used when
- /// the sub block does not belong to an extension.
- SubBlockFinished(AnyExtension, &'a [u8]),
- /// Decoded the last (or only) sub-block of a block.
- ///
- /// Indicates the label of the extension which might be unknown. A label of `0` is used when
- /// the sub block does not belong to an extension.
- BlockFinished(AnyExtension, &'a [u8]),
- /// Decoded all information of the next frame.
- ///
- /// The returned frame does **not** contain any owned image data.
- Frame(&'a Frame<'static>),
- /// Decoded some data of the current frame.
- Data(&'a [u8]),
- /// No more data available the current frame.
- DataEnd,
-
-}
-
-/// Internal state of the GIF decoder
-#[derive(Debug)]
-enum State {
- Magic(usize, [u8; 6]),
- U16Byte1(U16Value, u8),
- U16(U16Value),
- Byte(ByteValue),
- GlobalPalette(usize),
- BlockStart(Option<Block>),
- /// Block end, with remaining expected data. NonZero for invalid EOF.
- BlockEnd(u8),
- ExtensionBlock(AnyExtension),
- SkipBlock(usize),
- LocalPalette(usize),
- LzwInit(u8),
- DecodeSubBlock(usize),
- FrameDecoded,
- Trailer
-}
-use self::State::*;
-
-/// U16 values that may occur in a GIF image
-#[derive(Debug)]
-enum U16Value {
- /// Logical screen descriptor width
- ScreenWidth,
- /// Logical screen descriptor height
- ScreenHeight,
- /// Delay time
- Delay,
- /// Left frame offset
- ImageLeft,
- /// Top frame offset
- ImageTop,
- /// Frame width
- ImageWidth,
- /// Frame height
- ImageHeight,
-}
-
-/// Single byte screen descriptor values
-#[derive(Debug)]
-enum ByteValue {
- GlobalFlags,
- Background { table_size: usize },
- AspectRatio { table_size: usize },
- ControlFlags,
- ImageFlags,
- TransparentIdx,
- CodeSize,
-}
-
-/// GIF decoder which supports streaming
-pub struct StreamingDecoder {
- state: Option<State>,
- lzw_reader: Option<LzwDecoder>,
- decode_buffer: Vec<u8>,
- skip_extensions: bool,
- check_frame_consistency: bool,
- check_for_end_code: bool,
- allow_unknown_blocks: bool,
- version: Version,
- width: u16,
- height: u16,
- global_color_table: Vec<u8>,
- background_color: [u8; 4],
- /// ext buffer
- ext: ExtensionData,
- /// Frame data
- current: Option<Frame<'static>>,
-}
-
-/// One version number of the GIF standard.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-#[non_exhaustive]
-pub enum Version {
- /// Version 87a, from May 1987.
- V87a,
- /// Version 89a, from July 1989.
- V89a,
-}
-
-struct ExtensionData {
- id: AnyExtension,
- data: Vec<u8>,
- is_block_end: bool,
-}
-
-impl StreamingDecoder {
- /// Creates a new streaming decoder
- pub fn new() -> StreamingDecoder {
- let options = DecodeOptions::new();
- Self::with_options(&options)
- }
-
- pub(crate) fn with_options(options: &DecodeOptions) -> Self {
- StreamingDecoder {
- state: Some(Magic(0, [0; 6])),
- lzw_reader: None,
- decode_buffer: vec![],
- skip_extensions: true,
- check_frame_consistency: options.check_frame_consistency,
- check_for_end_code: options.check_for_end_code,
- allow_unknown_blocks: options.allow_unknown_blocks,
- version: Version::V87a,
- width: 0,
- height: 0,
- global_color_table: Vec::new(),
- background_color: [0, 0, 0, 0xFF],
- ext: ExtensionData {
- id: AnyExtension(0),
- data: Vec::with_capacity(256), // 0xFF + 1 byte length
- is_block_end: true,
- },
- current: None
- }
- }
-
- /// Updates the internal state of the decoder.
- ///
- /// Returns the number of bytes consumed from the input buffer
- /// and the last decoding result.
- pub fn update<'a>(&'a mut self, mut buf: &[u8])
- -> Result<(usize, Decoded<'a>), DecodingError> {
- // NOTE: Do not change the function signature without double-checking the
- // unsafe block!
- let len = buf.len();
- while buf.len() > 0 && self.state.is_some() {
- match self.next_state(buf) {
- Ok((bytes, Decoded::Nothing)) => {
- buf = &buf[bytes..]
- }
- Ok((bytes, Decoded::Trailer)) => {
- buf = &buf[bytes..];
- break
- }
- Ok((bytes, result)) => {
- buf = &buf[bytes..];
- return Ok(
- (len-buf.len(),
- // This transmute just casts the lifetime away. Since Rust only
- // has SESE regions, this early return cannot be worked out and
- // such that the borrow region of self includes the whole block.
- // The explixit lifetimes in the function signature ensure that
- // this is safe.
- // ### NOTE
- // To check that everything is sound, return the result without
- // the match (e.g. `return Ok(self.next_state(buf)?)`). If
- // it compiles the returned lifetime is correct.
- unsafe {
- mem::transmute::<Decoded, Decoded>(result)
- }
- ))
- }
- Err(err) => return Err(err)
- }
- }
- Ok((len-buf.len(), Decoded::Nothing))
-
- }
-
- /// Returns the data of the last extension that has been decoded.
- pub fn last_ext(&self) -> (AnyExtension, &[u8], bool) {
- (self.ext.id, &self.ext.data, self.ext.is_block_end)
- }
-
- #[inline(always)]
- /// Current frame info as a mutable ref.
- pub fn current_frame_mut<'a>(&'a mut self) -> &'a mut Frame<'static> {
- self.current.as_mut().unwrap()
- }
-
- #[inline(always)]
- /// Current frame info as a ref.
- pub fn current_frame<'a>(&'a self) -> &'a Frame<'static> {
- self.current.as_ref().unwrap()
- }
-
- /// Width of the image
- pub fn width(&self) -> u16 {
- self.width
- }
-
- /// Height of the image
- pub fn height(&self) -> u16 {
- self.height
- }
-
- /// The version number of the GIF standard used in this image.
- ///
- /// We suppose a minimum of `V87a` compatibility. This value will be reported until we have
- /// read the version information in the magic header bytes.
- pub fn version(&self) -> Version {
- self.version
- }
-
- /// Configure whether extensions are saved or skipped.
- #[deprecated = "Does not work as intended. In fact, doesn't do anything. This may disappear soon."]
- pub fn set_extensions(&mut self, extensions: Extensions) {
- self.skip_extensions = match extensions {
- Extensions::Skip => true,
- Extensions::Save => false,
- }
- }
-
- fn next_state<'a>(&'a mut self, buf: &[u8]) -> Result<(usize, Decoded<'a>), DecodingError> {
- macro_rules! goto (
- ($n:expr, $state:expr) => ({
- self.state = Some($state);
- Ok(($n, Decoded::Nothing))
- });
- ($state:expr) => ({
- self.state = Some($state);
- Ok((1, Decoded::Nothing))
- });
- ($n:expr, $state:expr, emit $res:expr) => ({
- self.state = Some($state);
- Ok(($n, $res))
- });
- ($state:expr, emit $res:expr) => ({
- self.state = Some($state);
- Ok((1, $res))
- })
- );
-
- let b = buf[0];
-
- // Driver should ensure that state is never None
- let state = self.state.take().unwrap();
- //println!("{:?}", state);
-
- match state {
- Magic(i, mut version) => if i < 6 {
- version[i] = b;
- goto!(Magic(i+1, version))
- } else if &version[..3] == b"GIF" {
- self.version = match &version[3..] {
- b"87a" => Version::V87a,
- b"89a" => Version::V89a,
- _ => return Err(DecodingError::format("unsupported GIF version"))
- };
- goto!(U16Byte1(U16Value::ScreenWidth, b))
- } else {
- Err(DecodingError::format("malformed GIF header"))
- },
- U16(next) => goto!(U16Byte1(next, b)),
- U16Byte1(next, value) => {
- use self::U16Value::*;
- let value = ((b as u16) << 8) | value as u16;
- match (next, value) {
- (ScreenWidth, width) => {
- self.width = width;
- goto!(U16(U16Value::ScreenHeight))
- },
- (ScreenHeight, height) => {
- self.height = height;
- goto!(Byte(ByteValue::GlobalFlags))
- },
- (Delay, delay) => {
- self.ext.data.push(value as u8);
- self.ext.data.push(b);
- self.current_frame_mut().delay = delay;
- goto!(Byte(ByteValue::TransparentIdx))
- },
- (ImageLeft, left) => {
- self.current_frame_mut().left = left;
- goto!(U16(U16Value::ImageTop))
- },
- (ImageTop, top) => {
- self.current_frame_mut().top = top;
- goto!(U16(U16Value::ImageWidth))
- },
- (ImageWidth, width) => {
- self.current_frame_mut().width = width;
- goto!(U16(U16Value::ImageHeight))
- },
- (ImageHeight, height) => {
- self.current_frame_mut().height = height;
- goto!(Byte(ByteValue::ImageFlags))
- }
- }
- }
- Byte(value) => {
- use self::ByteValue::*;
- match value {
- GlobalFlags => {
- let global_table = b & 0x80 != 0;
- let entries = if global_table {
- let entries = PLTE_CHANNELS*(1 << ((b & 0b111) + 1) as usize);
- self.global_color_table.reserve_exact(entries);
- entries
- } else {
- 0usize
- };
- goto!(Byte(Background { table_size: entries }))
- },
- Background { table_size } => {
- goto!(
- Byte(AspectRatio { table_size: table_size }),
- emit Decoded::BackgroundColor(b)
- )
- },
- AspectRatio { table_size } => {
- goto!(GlobalPalette(table_size))
- },
- ControlFlags => {
- self.ext.data.push(b);
- let control_flags = b;
- if control_flags & 1 != 0 {
- // Set to Some(...), gets overwritten later
- self.current_frame_mut().transparent = Some(0)
- }
- self.current_frame_mut().needs_user_input =
- control_flags & 0b10 != 0;
- self.current_frame_mut().dispose = match DisposalMethod::from_u8(
- (control_flags & 0b11100) >> 2
- ) {
- Some(method) => method,
- None => DisposalMethod::Any
- };
- goto!(U16(U16Value::Delay))
- }
- TransparentIdx => {
- self.ext.data.push(b);
- if let Some(ref mut idx) = self.current_frame_mut().transparent {
- *idx = b
- }
- goto!(SkipBlock(0))
- //goto!(AwaitBlockEnd)
- }
- ImageFlags => {
- let local_table = (b & 0b1000_0000) != 0;
- let interlaced = (b & 0b0100_0000) != 0;
- let table_size = b & 0b0000_0111;
-
- self.current_frame_mut().interlaced = interlaced;
-
- if self.check_frame_consistency {
- // Consistency checks.
- let (width, height) = (self.width, self.height);
- let frame = self.current_frame_mut();
- if width.checked_sub(frame.width) < Some(frame.left)
- || height.checked_sub(frame.height) < Some(frame.top)
- {
- return Err(DecodingError::format("frame descriptor is out-of-bounds"))
- }
- }
-
- if local_table {
- let entries = PLTE_CHANNELS * (1 << (table_size + 1));
-
- self.current_frame_mut().palette =
- Some(Vec::with_capacity(entries));
- goto!(LocalPalette(entries))
- } else {
- goto!(Byte(CodeSize))
- }
- },
- CodeSize => goto!(LzwInit(b))
- }
- }
- GlobalPalette(left) => {
- let n = cmp::min(left, buf.len());
- if left > 0 {
- self.global_color_table.extend_from_slice(&buf[..n]);
- goto!(n, GlobalPalette(left - n))
- } else {
- let idx = self.background_color[0];
- match self.global_color_table.chunks(PLTE_CHANNELS).nth(idx as usize) {
- Some(chunk) => self.background_color[..PLTE_CHANNELS]
- .copy_from_slice(&chunk[..PLTE_CHANNELS]),
- None => self.background_color[0] = 0
- }
- goto!(BlockStart(Block::from_u8(b)), emit Decoded::GlobalPalette(
- mem::replace(&mut self.global_color_table, Vec::new())
- ))
- }
- }
- BlockStart(type_) => {
- match type_ {
- Some(Block::Image) => {
- self.add_frame();
- goto!(U16Byte1(U16Value::ImageLeft, b), emit Decoded::BlockStart(Block::Image))
- }
- Some(Block::Extension) => {
- goto!(ExtensionBlock(AnyExtension(b)), emit Decoded::BlockStart(Block::Extension))
- }
- Some(Block::Trailer) => {
- goto!(0, State::Trailer, emit Decoded::BlockStart(Block::Trailer))
- }
- None => {
- if self.allow_unknown_blocks {
- goto!(SkipBlock(b as usize))
- } else {
- Err(DecodingError::format("unknown block type encountered"))
- }
- }
- }
- }
- BlockEnd(terminator) => {
- if terminator == 0 {
- if b == Block::Trailer as u8 {
- goto!(0, BlockStart(Some(Block::Trailer)))
- } else {
- goto!(BlockStart(Block::from_u8(b)))
- }
- } else {
- return Err(DecodingError::format(
- "expected block terminator not found"
- ))
- }
- }
- ExtensionBlock(id) => {
- use Extension::*;
- self.ext.id = id;
- self.ext.data.clear();
- self.ext.data.push(b);
- if let Some(ext) = Extension::from_u8(id.0) {
- match ext {
- Control => {
- goto!(self.read_control_extension(b)?)
- }
- Text | Comment | Application => {
- goto!(SkipBlock(b as usize))
- }
- }
- } else {
- return Err(DecodingError::format(
- "unknown extention block encountered"
- ))
- }
- }
- SkipBlock(left) => {
- let n = cmp::min(left, buf.len());
- if left > 0 {
- self.ext.data.extend_from_slice(&buf[..n]);
- goto!(n, SkipBlock(left - n))
- } else {
- if b == 0 {
- self.ext.is_block_end = true;
- goto!(BlockEnd(b), emit Decoded::BlockFinished(self.ext.id, &self.ext.data))
- } else {
- self.ext.is_block_end = false;
- goto!(SkipBlock(b as usize), emit Decoded::SubBlockFinished(self.ext.id, &self.ext.data))
- }
- }
- }
- LocalPalette(left) => {
- let n = cmp::min(left, buf.len());
- if left > 0 {
-
- self.current_frame_mut().palette
- .as_mut().unwrap().extend(buf[..n].iter().cloned());
- goto!(n, LocalPalette(left - n))
- } else {
- goto!(LzwInit(b))
- }
- }
- LzwInit(code_size) => {
- // LZW spec: max 12 bits per code
- if code_size > 11 {
- return Err(DecodingError::format(
- "invalid minimal code size"
- ))
- }
- self.lzw_reader = Some(LzwDecoder::new(BitOrder::Lsb, code_size));
- goto!(DecodeSubBlock(b as usize), emit Decoded::Frame(self.current_frame_mut()))
- }
- DecodeSubBlock(left) => {
- if left > 0 {
- let n = cmp::min(left, buf.len());
- let max_bytes = self.current_frame().required_bytes();
- let decoder = self.lzw_reader.as_mut().unwrap();
- if decoder.has_ended() {
- debug_assert!(n > 0, "Made forward progress after LZW end");
- return goto!(n, DecodeSubBlock(0), emit Decoded::Data(&[]));
- }
-
- let mut dummy_target;
- let decode_target;
-
- if self.decode_buffer.is_empty() {
- let size = (1 << 14).min(max_bytes);
- self.decode_buffer = vec![0; size];
- }
-
- if max_bytes == 0 {
- dummy_target = [0; 16];
- decode_target = &mut dummy_target[..];
- } else {
- decode_target = self.decode_buffer.as_mut_slice();
- }
-
- debug_assert!(!decode_target.is_empty(), "LZW decoding can make forward progress.");
- let decoded = decoder.decode_bytes(&buf[..n], decode_target);
-
- if let Err(err) = decoded.status {
- return Err(io::Error::new(io::ErrorKind::InvalidData, &*format!("{:?}", err)).into());
- }
-
- let bytes = &self.decode_buffer[..decoded.consumed_out.min(max_bytes)];
- let consumed = decoded.consumed_in;
- goto!(consumed, DecodeSubBlock(left - consumed), emit Decoded::Data(bytes))
- } else if b != 0 { // decode next sub-block
- goto!(DecodeSubBlock(b as usize))
- } else {
- let max_bytes = self.current_frame().required_bytes();
- // The end of the lzw stream is only reached if left == 0 and an additional call
- // to `decode_bytes` results in an empty slice.
- let decoder = self.lzw_reader.as_mut().unwrap();
- // Some mutable bytes to decode into. We need this for forward progress in
- // `lzw`. However, in some cases we do not actually need any bytes, when
- // `max_bytes` is `0`.
- let mut dummy_target;
- let decode_target;
-
- if self.decode_buffer.is_empty() {
- let size = (1 << 14).min(max_bytes);
- self.decode_buffer = vec![0; size];
- }
-
- if max_bytes == 0 {
- dummy_target = [0; 16];
- decode_target = &mut dummy_target[..];
- } else {
- decode_target = self.decode_buffer.as_mut_slice();
- }
-
- debug_assert!(!decode_target.is_empty(), "LZW decoding can make forward progress.");
- let decoded = decoder.decode_bytes(&[], decode_target);
-
- match decoded.status {
- Ok(LzwStatus::Done) | Ok(LzwStatus::Ok) => {},
- Ok(LzwStatus::NoProgress) => {
- if self.check_for_end_code {
- return Err(io::Error::new(io::ErrorKind::InvalidData, "No end code in lzw stream").into());
- } else {
- self.current = None;
- return goto!(0, FrameDecoded, emit Decoded::DataEnd);
- }
- },
- Err(err) => {
- return Err(io::Error::new(io::ErrorKind::InvalidData, &*format!("{:?}", err)).into());
- }
- }
- let bytes = &self.decode_buffer[..decoded.consumed_out.min(max_bytes)];
-
- if bytes.len() > 0 {
- goto!(0, DecodeSubBlock(0), emit Decoded::Data(bytes))
- } else {
- // end of image data reached
- self.current = None;
- goto!(0, FrameDecoded, emit Decoded::DataEnd)
- }
- }
- }
- FrameDecoded => {
- goto!(BlockEnd(b))
- }
- Trailer => {
- self.state = None;
- Ok((1, Decoded::Trailer))
- //panic!("EOF {:?}", self)
- }
- }
- }
-
- fn read_control_extension(&mut self, b: u8) -> Result<State, DecodingError> {
- self.add_frame();
- self.ext.data.push(b);
- if b != 4 {
- return Err(DecodingError::format(
- "control extension has wrong length"
- ))
- }
- Ok(Byte(ByteValue::ControlFlags))
- }
-
- fn add_frame(&mut self) {
- if self.current.is_none() {
- self.current = Some(Frame::default())
- }
- }
-}
-
-#[test]
-fn error_cast() {
- let _ : Box<dyn error::Error> = DecodingError::Format(DecodingFormatError::new("testing")).into();
-}