diff options
Diffstat (limited to 'vendor/gif/src')
-rw-r--r-- | vendor/gif/src/common.rs | 346 | ||||
-rw-r--r-- | vendor/gif/src/encoder.rs | 434 | ||||
-rw-r--r-- | vendor/gif/src/lib.rs | 154 | ||||
-rw-r--r-- | vendor/gif/src/reader/decoder.rs | 724 | ||||
-rw-r--r-- | vendor/gif/src/reader/mod.rs | 522 | ||||
-rw-r--r-- | vendor/gif/src/traits.rs | 49 |
6 files changed, 0 insertions, 2229 deletions
diff --git a/vendor/gif/src/common.rs b/vendor/gif/src/common.rs deleted file mode 100644 index 20ba99b..0000000 --- a/vendor/gif/src/common.rs +++ /dev/null @@ -1,346 +0,0 @@ -use std::borrow::Cow; -use std::collections::HashMap; -use std::collections::HashSet; - -/// Disposal method -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -#[repr(u8)] -pub enum DisposalMethod { - /// StreamingDecoder is not required to take any action. - Any = 0, - /// Do not dispose. - Keep = 1, - /// Restore to background color. - Background = 2, - /// Restore to previous. - Previous = 3, -} - -impl DisposalMethod { - /// Converts `u8` to `Option<Self>` - pub fn from_u8(n: u8) -> Option<DisposalMethod> { - match n { - 0 => Some(DisposalMethod::Any), - 1 => Some(DisposalMethod::Keep), - 2 => Some(DisposalMethod::Background), - 3 => Some(DisposalMethod::Previous), - _ => None - } - } -} - -/// Known GIF block labels. -/// -/// Note that the block uniquely specifies the layout of bytes that follow and how they are -/// framed. For example, the header always has a fixed length but is followed by a variable amount -/// of additional data. An image descriptor may be followed by a local color table depending on -/// information read in it. Therefore, it doesn't make sense to continue parsing after encountering -/// an unknown block as the semantics of following bytes are unclear. -/// -/// The extension block provides a common framing for an arbitrary amount of application specific -/// data which may be ignored. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -#[repr(u8)] -pub enum Block { - /// Image block. - Image = 0x2C, - /// Extension block. - Extension = 0x21, - /// Image trailer. - Trailer = 0x3B, -} - -impl Block { - /// Converts `u8` to `Option<Self>` - pub fn from_u8(n: u8) -> Option<Block> { - match n { - 0x2C => Some(Block::Image), - 0x21 => Some(Block::Extension), - 0x3B => Some(Block::Trailer), - _ => None - } - } -} - -/// A newtype wrapper around an arbitrary extension ID. -/// -/// An extension is some amount of byte data organized in sub-blocks so that one can skip over it -/// without knowing the semantics. Though technically you likely want to use a `Application` -/// extension, the library tries to stay flexible here. -/// -/// This allows us to customize the set of impls compared to a raw `u8`. It also clarifies the -/// intent and gives some inherent methods for interoperability with known extension types. -#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] -pub struct AnyExtension(pub u8); - -/// Known GIF extension labels. -/// -/// These are extensions which may be interpreted by the library and to which a specification with -/// the internal data layout is known. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -#[repr(u8)] -pub enum Extension { - /// Plain Text extension. - /// - /// This instructs the decoder to render a text as characters in a grid of cells, in a - /// mono-spaced font of its choosing. This is seldom actually implemented and ignored by - /// ImageMagick. The color is always taken from the global table which further complicates any - /// use. No real information on the frame sequencing of this block is available in the - /// standard. - Text = 0x01, - /// Control extension. - Control = 0xF9, - /// Comment extension. - Comment = 0xFE, - /// Application extension. - /// - /// See [ImageMagick] for an idea of commonly recognized extensions. - /// - /// [ImageMagick]: https://github.com/ImageMagick/ImageMagick/blob/b0b58c6303195928060f55f9c3ca8233ab7f7733/coders/gif.c#L1128 - Application = 0xFF, -} - -impl AnyExtension { - /// Decode the label as a known extension. - pub fn into_known(self) -> Option<Extension> { - Extension::from_u8(self.0) - } -} - -impl From<Extension> for AnyExtension { - fn from(ext: Extension) -> Self { - AnyExtension(ext as u8) - } -} - -impl Extension { - /// Converts `u8` to a `Extension` if it is known. - pub fn from_u8(n: u8) -> Option<Extension> { - match n { - 0x01 => Some(Extension::Text), - 0xF9 => Some(Extension::Control), - 0xFE => Some(Extension::Comment), - 0xFF => Some(Extension::Application), - _ => None - } - } -} - -/// A GIF frame -#[derive(Debug, Clone)] -pub struct Frame<'a> { - /// Frame delay in units of 10 ms. - pub delay: u16, - /// Disposal method. - pub dispose: DisposalMethod, - /// Transparent index (if available). - pub transparent: Option<u8>, - /// True if the frame needs user input to be displayed. - pub needs_user_input: bool, - /// Offset from the top border of the canvas. - pub top: u16, - /// Offset from the left border of the canvas. - pub left: u16, - /// Width of the frame. - pub width: u16, - /// Height of the frame. - pub height: u16, - /// True if the image is interlaced. - pub interlaced: bool, - /// Frame local color palette if available. - pub palette: Option<Vec<u8>>, - /// Buffer containing the image data. - /// Only indices unless configured differently. - pub buffer: Cow<'a, [u8]> -} - -impl<'a> Default for Frame<'a> { - fn default() -> Frame<'a> { - Frame { - delay: 0, - dispose: DisposalMethod::Keep, - transparent: None, - needs_user_input: false, - top: 0, - left: 0, - width: 0, - height: 0, - interlaced: false, - palette: None, - buffer: Cow::Borrowed(&[]) - } - } -} - -impl Frame<'static> { - /// Creates a frame from pixels in RGBA format. - /// - /// This is a lossy method. The `gif` format does not support arbitrary alpha but only a 1-bit - /// transparency mask per pixel. Any non-zero alpha value will be interpreted as a fully opaque - /// pixel. Additionally, only 256 colors can appear in a single frame. The palette will be - /// reduced by the NeuQuant algorithm if necessary. Different frames have independent palettes. - /// - /// *Note: This method is not optimized for speed.* - /// - /// # Panics: - /// * If the length of pixels does not equal `width * height * 4`. - #[cfg(feature = "color_quant")] - pub fn from_rgba(width: u16, height: u16, pixels: &mut [u8]) -> Frame<'static> { - Frame::from_rgba_speed(width, height, pixels, 1) - } - - /// Creates a frame from pixels in RGBA format. - /// - /// `speed` is a value in the range [1, 30]. - /// The higher the value the faster it runs at the cost of image quality. - /// A `speed` of 10 is a good compromise between speed and quality. - /// - /// This is a lossy method. The `gif` format does not support arbitrary alpha but only a 1-bit - /// transparency mask per pixel. Any non-zero alpha value will be interpreted as a fully opaque - /// pixel. Additionally, only 256 colors can appear in a single frame. The palette will be - /// reduced by the NeuQuant algorithm if necessary. Different frames have independent palettes. - /// - /// # Panics: - /// * If the length of pixels does not equal `width * height * 4`. - /// * If `speed < 1` or `speed > 30` - #[cfg(feature = "color_quant")] - pub fn from_rgba_speed(width: u16, height: u16, pixels: &mut [u8], speed: i32) -> Frame<'static> { - assert_eq!(width as usize * height as usize * 4, pixels.len(), "Too much or too little pixel data for the given width and height to create a GIF Frame"); - assert!(speed >= 1 && speed <= 30, "speed needs to be in the range [1, 30]"); - let mut transparent = None; - for pix in pixels.chunks_exact_mut(4) { - if pix[3] != 0 { - pix[3] = 0xFF; - } else { - transparent = Some([pix[0], pix[1], pix[2], pix[3]]) - } - } - - // Attempt to build a palette of all colors. If we go over 256 colors, - // switch to the NeuQuant algorithm. - let mut colors: HashSet<(u8, u8, u8, u8)> = HashSet::new(); - for pixel in pixels.chunks_exact(4) { - if colors.insert((pixel[0], pixel[1], pixel[2], pixel[3])) && colors.len() > 256 { - // > 256 colours, let's use NeuQuant. - let nq = color_quant::NeuQuant::new(speed, 256, pixels); - - return Frame { - width, - height, - buffer: Cow::Owned(pixels.chunks_exact(4).map(|pix| nq.index_of(pix) as u8).collect()), - palette: Some(nq.color_map_rgb()), - transparent: transparent.map(|t| nq.index_of(&t) as u8), - ..Frame::default() - }; - } - } - - // Palette size <= 256 elements, we can build an exact palette. - let mut colors_vec: Vec<(u8, u8, u8, u8)> = colors.into_iter().collect(); - colors_vec.sort(); - let palette = colors_vec.iter().flat_map(|&(r, g, b, _a)| [r, g, b]).collect(); - let colors_lookup: HashMap<(u8, u8, u8, u8), u8> = colors_vec.into_iter().zip(0..=255).collect(); - - let index_of = | pixel: &[u8] | - *colors_lookup.get(&(pixel[0], pixel[1], pixel[2], pixel[3])).unwrap(); - - return Frame { - width, - height, - buffer: Cow::Owned(pixels.chunks_exact(4).map(|pix| index_of(pix)).collect()), - palette: Some(palette), - transparent: transparent.map(|t| index_of(&t)), - ..Frame::default() - } - } - - /// Creates a frame from a palette and indexed pixels. - /// - /// # Panics: - /// * If the length of pixels does not equal `width * height`. - /// * If the length of palette > `256 * 3`. - pub fn from_palette_pixels(width: u16, height: u16, pixels: &[u8], palette: &[u8], transparent: Option<u8>) -> Frame<'static> { - assert_eq!(width as usize * height as usize, pixels.len(), "Too many or too little pixels for the given width and height to create a GIF Frame"); - assert!(palette.len() <= 256*3, "Too many palette values to create a GIF Frame"); - - Frame { - width, - height, - buffer: Cow::Owned(pixels.to_vec()), - palette: Some(palette.to_vec()), - transparent, - ..Frame::default() - } - } - - /// Creates a frame from indexed pixels in the global palette. - /// - /// # Panics: - /// * If the length of pixels does not equal `width * height`. - pub fn from_indexed_pixels(width: u16, height: u16, pixels: &[u8], transparent: Option<u8>) -> Frame<'static> { - assert_eq!(width as usize * height as usize, pixels.len(), "Too many or too little pixels for the given width and height to create a GIF Frame"); - - Frame { - width, - height, - buffer: Cow::Owned(pixels.to_vec()), - palette: None, - transparent, - ..Frame::default() - } - } - - /// Creates a frame from pixels in RGB format. - /// - /// This is a lossy method. In the `gif` format only 256 colors can appear in a single frame. - /// The palette will be reduced by the NeuQuant algorithm if necessary. Different frames have - /// independent palettes. - /// - /// *Note: This method is not optimized for speed.* - /// - /// # Panics: - /// * If the length of pixels does not equal `width * height * 3`. - #[cfg(feature = "color_quant")] - pub fn from_rgb(width: u16, height: u16, pixels: &[u8]) -> Frame<'static> { - Frame::from_rgb_speed(width, height, pixels, 1) - } - - /// Creates a frame from pixels in RGB format. - /// - /// `speed` is a value in the range [1, 30]. - /// - /// This is a lossy method. In the `gif` format only 256 colors can appear in a single frame. - /// The palette will be reduced by the NeuQuant algorithm if necessary. Different frames have - /// independent palettes. - /// - /// The higher the value the faster it runs at the cost of image quality. - /// A `speed` of 10 is a good compromise between speed and quality. - /// - /// # Panics: - /// * If the length of pixels does not equal `width * height * 3`. - /// * If `speed < 1` or `speed > 30` - #[cfg(feature = "color_quant")] - pub fn from_rgb_speed(width: u16, height: u16, pixels: &[u8], speed: i32) -> Frame<'static> { - assert_eq!(width as usize * height as usize * 3, pixels.len(), "Too much or too little pixel data for the given width and height to create a GIF Frame"); - let mut vec: Vec<u8> = Vec::with_capacity(pixels.len() + width as usize * height as usize); - for v in pixels.chunks_exact(3) { - vec.extend_from_slice(&[v[0], v[1], v[2], 0xFF]) - } - Frame::from_rgba_speed(width, height, &mut vec, speed) - } - - pub(crate) fn required_bytes(&self) -> usize { - usize::from(self.width) * usize::from(self.height) - } -} - -#[test] -#[cfg(feature = "color_quant")] -// Creating the `colors_lookup` hashmap in Frame::from_rgba_speed panics due to -// overflow while bypassing NeuQuant and zipping a RangeFrom with 256 colors. -// Changing .zip(0_u8..) to .zip(0_u8..=255) fixes this issue. -fn rgba_speed_avoid_panic_256_colors() { - let side = 16; - let pixel_data: Vec<u8> = (0..=255).map(|a| vec![a, a, a]).flatten().collect(); - Frame::from_rgb(side, side, &pixel_data); -} diff --git a/vendor/gif/src/encoder.rs b/vendor/gif/src/encoder.rs deleted file mode 100644 index 693a8cb..0000000 --- a/vendor/gif/src/encoder.rs +++ /dev/null @@ -1,434 +0,0 @@ -//! # Minimal gif encoder -use std::io; -use std::io::prelude::*; -use std::fmt; -use std::error; -use std::borrow::Cow; - -use weezl::{BitOrder, encode::Encoder as LzwEncoder}; - -use crate::traits::{WriteBytesExt}; -use crate::common::{AnyExtension, Block, DisposalMethod, Extension, Frame}; - -#[derive(Debug)] -enum FormatErrorKind { - /// The image has too many colors. - TooManyColors, - /// The image has no color palette which is required. - MissingColorPalette, -} - -/// The image has incorrect properties, making it impossible to encode as a gif. -#[derive(Debug)] -pub struct EncodingFormatError { - kind: FormatErrorKind -} - -impl error::Error for EncodingFormatError {} -impl fmt::Display for EncodingFormatError { - fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { - match self.kind { - FormatErrorKind::TooManyColors => write!(fmt, "the image has too many colors"), - FormatErrorKind::MissingColorPalette => write!(fmt, "the GIF format requires a color palette but none was given") - } - } -} - -impl From<FormatErrorKind> for EncodingFormatError { - fn from(kind: FormatErrorKind) -> Self { - EncodingFormatError { kind } - } -} - -#[derive(Debug)] -/// Encoding error. -pub enum EncodingError { - /// Returned if the to image is not encodable as a gif. - Format(EncodingFormatError), - /// Wraps `std::io::Error`. - Io(io::Error), -} - -impl fmt::Display for EncodingError { - fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - match self { - EncodingError::Io(err) => err.fmt(fmt), - EncodingError::Format(err) => err.fmt(fmt), - } - } -} - -impl error::Error for EncodingError { - fn source(&self) -> Option<&(dyn error::Error + 'static)> { - match self { - EncodingError::Io(err) => Some(err), - EncodingError::Format(err) => Some(err), - } - } -} - -impl From<io::Error> for EncodingError { - fn from(err: io::Error) -> Self { - EncodingError::Io(err) - } -} - -impl From<EncodingFormatError> for EncodingError { - fn from(err: EncodingFormatError) -> Self { - EncodingError::Format(err) - } -} - -impl From<FormatErrorKind> for EncodingError { - fn from(kind: FormatErrorKind) -> Self { - EncodingError::Format(kind.into()) - } -} - - -/// Number of repetitions -#[derive(Copy, Clone, Debug)] -pub enum Repeat { - /// Finite number of repetitions - Finite(u16), - /// Infinite number of repetitions - Infinite -} - -/// Extension data. -pub enum ExtensionData { - /// Control extension. Use `ExtensionData::new_control_ext` to construct. - Control { - /// Flags. - flags: u8, - /// Frame delay. - delay: u16, - /// Transparent index. - trns: u8 - }, - /// Sets the number of repetitions - Repetitions(Repeat) -} - -impl ExtensionData { - /// Constructor for control extension data. - /// - /// `delay` is given in units of 10 ms. - pub fn new_control_ext(delay: u16, dispose: DisposalMethod, - needs_user_input: bool, trns: Option<u8>) -> ExtensionData { - let mut flags = 0; - let trns = match trns { - Some(trns) => { - flags |= 1; - trns as u8 - }, - None => 0 - }; - flags |= (needs_user_input as u8) << 1; - flags |= (dispose as u8) << 2; - ExtensionData::Control { - flags: flags, - delay: delay, - trns: trns - } - } -} - -impl<W: Write> Encoder<W> { - /// Creates a new encoder. - /// - /// `global_palette` gives the global color palette in the format `[r, g, b, ...]`, - /// if no global palette shall be used an empty slice may be supplied. - pub fn new(w: W, width: u16, height: u16, global_palette: &[u8]) -> Result<Self, EncodingError> { - let buffer_size = (width as usize) * (height as usize); - Encoder { - w: Some(w), - global_palette: false, - width: width, - height: height, - buffer: Vec::with_capacity(buffer_size) - }.write_global_palette(global_palette) - } - - /// Write an extension block that signals a repeat behaviour. - pub fn set_repeat(&mut self, repeat: Repeat) -> Result<(), EncodingError> { - self.write_extension(ExtensionData::Repetitions(repeat)) - } - - /// Writes the global color palette. - pub fn write_global_palette(mut self, palette: &[u8]) -> Result<Self, EncodingError> { - self.global_palette = true; - let mut flags = 0; - flags |= 0b1000_0000; - let num_colors = palette.len() / 3; - if num_colors > 256 { - return Err(EncodingError::from(FormatErrorKind::TooManyColors)); - } - // Size of global color table. - flags |= flag_size(num_colors); - // Color resolution .. FIXME. This is mostly ignored (by ImageMagick at least) but hey, we - // should use some sensible value here or even allow configuring it? - flags |= flag_size(num_colors) << 4; // wtf flag - self.write_screen_desc(flags)?; - self.write_color_table(palette)?; - Ok(self) - } - - /// Writes a frame to the image. - /// - /// Note: This function also writes a control extension if necessary. - pub fn write_frame(&mut self, frame: &Frame) -> Result<(), EncodingError> { - self.write_frame_header(frame)?; - self.write_image_block(&frame.buffer) - } - - fn write_frame_header(&mut self, frame: &Frame) -> Result<(), EncodingError> { - // TODO commented off to pass test in lib.rs - //if frame.delay > 0 || frame.transparent.is_some() { - self.write_extension(ExtensionData::new_control_ext( - frame.delay, - frame.dispose, - frame.needs_user_input, - frame.transparent - - ))?; - //} - let writer = self.w.as_mut().unwrap(); - writer.write_le(Block::Image as u8)?; - writer.write_le(frame.left)?; - writer.write_le(frame.top)?; - writer.write_le(frame.width)?; - writer.write_le(frame.height)?; - let mut flags = 0; - if frame.interlaced { - flags |= 0b0100_0000; - } - match frame.palette { - Some(ref palette) => { - flags |= 0b1000_0000; - let num_colors = palette.len() / 3; - if num_colors > 256 { - return Err(EncodingError::from(FormatErrorKind::TooManyColors)); - } - flags |= flag_size(num_colors); - writer.write_le(flags)?; - self.write_color_table(palette) - }, - None => if !self.global_palette { - Err(EncodingError::from(FormatErrorKind::MissingColorPalette)) - } else { - writer.write_le(flags).map_err(Into::into) - } - } - } - - fn write_image_block(&mut self, data: &[u8]) -> Result<(), EncodingError> { - self.buffer.clear(); - lzw_encode(data, &mut self.buffer); - - let writer = self.w.as_mut().unwrap(); - Self::write_encoded_image_block(writer, &self.buffer) - } - - fn write_encoded_image_block(writer: &mut W, data_with_min_code_size: &[u8]) -> Result<(), EncodingError> { - let (&min_code_size, data) = data_with_min_code_size.split_first().unwrap_or((&2, &[])); - writer.write_le(min_code_size)?; - - // Write blocks. `chunks_exact` seems to be slightly faster - // than `chunks` according to both Rust docs and benchmark results. - let mut iter = data.chunks_exact(0xFF); - while let Some(full_block) = iter.next() { - writer.write_le(0xFFu8)?; - writer.write_all(full_block)?; - } - let last_block = iter.remainder(); - if !last_block.is_empty() { - writer.write_le(last_block.len() as u8)?; - writer.write_all(last_block)?; - } - writer.write_le(0u8).map_err(Into::into) - } - - fn write_color_table(&mut self, table: &[u8]) -> Result<(), EncodingError> { - let writer = self.w.as_mut().unwrap(); - let num_colors = table.len() / 3; - if num_colors > 256 { - return Err(EncodingError::from(FormatErrorKind::TooManyColors)); - } - let size = flag_size(num_colors); - writer.write_all(&table[..num_colors * 3])?; - // Waste some space as of gif spec - for _ in 0..((2 << size) - num_colors) { - writer.write_all(&[0, 0, 0])? - } - Ok(()) - } - - /// Writes an extension to the image. - /// - /// It is normally not necessary to call this method manually. - pub fn write_extension(&mut self, extension: ExtensionData) -> Result<(), EncodingError> { - use self::ExtensionData::*; - // 0 finite repetitions can only be achieved - // if the corresponting extension is not written - if let Repetitions(Repeat::Finite(0)) = extension { - return Ok(()) - } - let writer = self.w.as_mut().unwrap(); - writer.write_le(Block::Extension as u8)?; - match extension { - Control { flags, delay, trns } => { - writer.write_le(Extension::Control as u8)?; - writer.write_le(4u8)?; - writer.write_le(flags)?; - writer.write_le(delay)?; - writer.write_le(trns)?; - } - Repetitions(repeat) => { - writer.write_le(Extension::Application as u8)?; - writer.write_le(11u8)?; - writer.write_all(b"NETSCAPE2.0")?; - writer.write_le(3u8)?; - writer.write_le(1u8)?; - match repeat { - Repeat::Finite(no) => writer.write_le(no)?, - Repeat::Infinite => writer.write_le(0u16)?, - } - } - } - writer.write_le(0u8).map_err(Into::into) - } - - /// Writes a raw extension to the image. - /// - /// This method can be used to write an unsupported extension to the file. `func` is the extension - /// identifier (e.g. `Extension::Application as u8`). `data` are the extension payload blocks. If any - /// contained slice has a lenght > 255 it is automatically divided into sub-blocks. - pub fn write_raw_extension(&mut self, func: AnyExtension, data: &[&[u8]]) -> io::Result<()> { - let writer = self.w.as_mut().unwrap(); - writer.write_le(Block::Extension as u8)?; - writer.write_le(func.0)?; - for block in data { - for chunk in block.chunks(0xFF) { - writer.write_le(chunk.len() as u8)?; - writer.write_all(chunk)?; - } - } - writer.write_le(0u8) - } - - /// Writes a frame to the image, but expects `Frame.buffer` to contain LZW-encoded data - /// from [`Frame::make_lzw_pre_encoded`]. - /// - /// Note: This function also writes a control extension if necessary. - pub fn write_lzw_pre_encoded_frame(&mut self, frame: &Frame) -> Result<(), EncodingError> { - self.write_frame_header(frame)?; - let writer = self.w.as_mut().unwrap(); - Self::write_encoded_image_block(writer, &frame.buffer) - } - - /// Writes the logical screen desriptor - fn write_screen_desc(&mut self, flags: u8) -> io::Result<()> { - let writer = self.w.as_mut().unwrap(); - writer.write_all(b"GIF89a")?; - writer.write_le(self.width)?; - writer.write_le(self.height)?; - writer.write_le(flags)?; // packed field - writer.write_le(0u8)?; // bg index - writer.write_le(0u8) // aspect ratio - } - - /// Gets a reference to the writer instance used by this encoder. - pub fn get_ref(&self) -> &W { - self.w.as_ref().unwrap() - } - - /// Gets a mutable reference to the writer instance used by this encoder. - /// - /// It is inadvisable to directly write to the underlying writer. - pub fn get_mut(&mut self) -> &mut W { - self.w.as_mut().unwrap() - } - - /// Returns writer instance used by this encoder - pub fn into_inner(mut self) -> io::Result<W> { - self.write_trailer()?; - Ok(self.w.take().unwrap()) - } - - /// Write the final tailer. - fn write_trailer(&mut self) -> io::Result<()> { - self.w.as_mut().unwrap().write_le(Block::Trailer as u8) - } -} - -/// Encodes the data into the provided buffer. -/// -/// The first byte is the minimum code size, followed by LZW data. -fn lzw_encode(data: &[u8], buffer: &mut Vec<u8>) { - let min_code_size = match flag_size(1 + data.iter().copied().max().unwrap_or(0) as usize) + 1 { - 1 => 2, // As per gif spec: The minimal code size has to be >= 2 - n => n - }; - buffer.push(min_code_size); - let mut enc = LzwEncoder::new(BitOrder::Lsb, min_code_size); - let len = enc.into_vec(buffer).encode_all(data).consumed_out; - buffer.truncate(len+1); -} - -impl Frame<'_> { - /// Replace frame's buffer with a LZW-compressed one for use with [`Encoder::write_lzw_pre_encoded_frame`]. - /// - /// Frames can be compressed in any order, separately from the `Encoder`, which can be used to compress frames in parallel. - pub fn make_lzw_pre_encoded(&mut self) { - let mut buffer = Vec::with_capacity(self.buffer.len() / 2); - lzw_encode(&self.buffer, &mut buffer); - self.buffer = Cow::Owned(buffer); - } -} - -/// GIF encoder. -pub struct Encoder<W: Write> { - w: Option<W>, - global_palette: bool, - width: u16, - height: u16, - buffer: Vec<u8> -} - -impl<W: Write> Drop for Encoder<W> { - - #[cfg(feature = "raii_no_panic")] - fn drop(&mut self) { - if self.w.is_some() { - let _ = self.write_trailer(); - } - } - - #[cfg(not(feature = "raii_no_panic"))] - fn drop(&mut self) { - if self.w.is_some() { - self.write_trailer().unwrap(); - } - } -} - -// Color table size converted to flag bits -fn flag_size(size: usize) -> u8 { - match size { - 0 ..=2 => 0, - 3 ..=4 => 1, - 5 ..=8 => 2, - 9 ..=16 => 3, - 17 ..=32 => 4, - 33 ..=64 => 5, - 65 ..=128 => 6, - 129..=256 => 7, - _ => 7 - } -} - -#[test] -fn error_cast() { - let _ : Box<dyn error::Error> = EncodingError::from(FormatErrorKind::MissingColorPalette).into(); -} diff --git a/vendor/gif/src/lib.rs b/vendor/gif/src/lib.rs deleted file mode 100644 index 8eb2a61..0000000 --- a/vendor/gif/src/lib.rs +++ /dev/null @@ -1,154 +0,0 @@ -//! # GIF en- and decoding library [![Build Status](https://github.com/image-rs/image-gif/workflows/Rust%20CI/badge.svg)](https://github.com/image-rs/image-gif/actions) -//! -//! GIF en- and decoder written in Rust ([API Documentation](https://docs.rs/gif)). -//! -//! # GIF encoding and decoding library -//! -//! This library provides all functions necessary to de- and encode GIF files. -//! -//! ## High level interface -//! -//! The high level interface consists of the two types -//! [`Encoder`](struct.Encoder.html) and [`Decoder`](struct.Decoder.html). -//! -//! ### Decoding GIF files -//! -//! ```rust -//! // Open the file -//! use std::fs::File; -//! let mut decoder = gif::DecodeOptions::new(); -//! // Configure the decoder such that it will expand the image to RGBA. -//! decoder.set_color_output(gif::ColorOutput::RGBA); -//! // Read the file header -//! let file = File::open("tests/samples/sample_1.gif").unwrap(); -//! let mut decoder = decoder.read_info(file).unwrap(); -//! while let Some(frame) = decoder.read_next_frame().unwrap() { -//! // Process every frame -//! } -//! ``` -//! -//! -//! -//! ### Encoding GIF files -//! -//! The encoder can be used so save simple computer generated images: -//! -//! ```rust -//! use gif::{Frame, Encoder, Repeat}; -//! use std::fs::File; -//! use std::borrow::Cow; -//! -//! let color_map = &[0xFF, 0xFF, 0xFF, 0, 0, 0]; -//! let (width, height) = (6, 6); -//! let mut beacon_states = [[ -//! 0, 0, 0, 0, 0, 0, -//! 0, 1, 1, 0, 0, 0, -//! 0, 1, 1, 0, 0, 0, -//! 0, 0, 0, 1, 1, 0, -//! 0, 0, 0, 1, 1, 0, -//! 0, 0, 0, 0, 0, 0, -//! ], [ -//! 0, 0, 0, 0, 0, 0, -//! 0, 1, 1, 0, 0, 0, -//! 0, 1, 0, 0, 0, 0, -//! 0, 0, 0, 0, 1, 0, -//! 0, 0, 0, 1, 1, 0, -//! 0, 0, 0, 0, 0, 0, -//! ]]; -//! let mut image = File::create("tests/samples/beacon.gif").unwrap();; -//! let mut encoder = Encoder::new(&mut image, width, height, color_map).unwrap(); -//! encoder.set_repeat(Repeat::Infinite).unwrap(); -//! for state in &beacon_states { -//! let mut frame = Frame::default(); -//! frame.width = width; -//! frame.height = height; -//! frame.buffer = Cow::Borrowed(&*state); -//! encoder.write_frame(&frame).unwrap(); -//! } -//! ``` -//! -//! [`Frame::from_*`](struct.Frame.html) can be used to convert a true color image to a paletted -//! image with a maximum of 256 colors: -//! -//! ```rust -//! # #[cfg(feature = "color_quant")] { -//! use std::fs::File; -//! -//! // Get pixel data from some source -//! let mut pixels: Vec<u8> = vec![0; 30_000]; -//! // Create frame from data -//! let frame = gif::Frame::from_rgb(100, 100, &mut *pixels); -//! // Create encoder -//! let mut image = File::create("target/indexed_color.gif").unwrap(); -//! let mut encoder = gif::Encoder::new(&mut image, frame.width, frame.height, &[]).unwrap(); -//! // Write frame to file -//! encoder.write_frame(&frame).unwrap(); -//! # } -//! ``` - -// TODO: make this compile -// ```rust -// use gif::{Frame, Encoder}; -// use std::fs::File; -// let color_map = &[0, 0, 0, 0xFF, 0xFF, 0xFF]; -// let mut frame = Frame::default(); -// // Generate checkerboard lattice -// for (i, j) in (0..10).zip(0..10) { -// frame.buffer.push(if (i * j) % 2 == 0 { -// 1 -// } else { -// 0 -// }) -// } -// # (|| { -// { -// let mut file = File::create("test.gif")?; -// let mut encoder = Encoder::new(&mut file, 100, 100); -// encoder.write_global_palette(color_map)?.write_frame(&frame) -// } -// # })().unwrap(); -// ``` -#![deny(missing_docs)] -#![cfg(feature = "std")] - -mod traits; -mod common; -mod reader; -mod encoder; - -pub use crate::common::{AnyExtension, Block, Extension, DisposalMethod, Frame}; - -pub use crate::reader::{StreamingDecoder, Decoded, DecodingError, DecodingFormatError}; -/// StreamingDecoder configuration parameters -pub use crate::reader::{ColorOutput, MemoryLimit, Extensions}; -pub use crate::reader::{DecodeOptions, Decoder, Version}; - -pub use crate::encoder::{Encoder, ExtensionData, Repeat, EncodingError}; - -#[cfg(test)] -#[test] -fn round_trip() { - use std::io::prelude::*; - use std::fs::File; - let mut data = vec![]; - File::open("tests/samples/sample_1.gif").unwrap().read_to_end(&mut data).unwrap(); - let mut decoder = Decoder::new(&*data).unwrap(); - let palette: Vec<u8> = decoder.palette().unwrap().into(); - let frame = decoder.read_next_frame().unwrap().unwrap(); - let mut data2 = vec![]; - { - let mut encoder = Encoder::new(&mut data2, frame.width, frame.height, &palette).unwrap(); - encoder.write_frame(frame).unwrap(); - } - assert_eq!(&data[..], &data2[..]) -} - -macro_rules! insert_as_doc { - { $content:expr } => { - #[doc = $content] extern { } - } -} - -// Provides the README.md as doc, to ensure the example works! -#[cfg(feature = "color_quant")] -insert_as_doc!(include_str!("../README.md")); 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(); -} diff --git a/vendor/gif/src/reader/mod.rs b/vendor/gif/src/reader/mod.rs deleted file mode 100644 index a453e79..0000000 --- a/vendor/gif/src/reader/mod.rs +++ /dev/null @@ -1,522 +0,0 @@ -use std::borrow::Cow; -use std::io; -use std::cmp; -use std::mem; -use std::iter; -use std::io::prelude::*; - -use crate::common::{Block, Frame}; - -mod decoder; -pub use self::decoder::{ - PLTE_CHANNELS, StreamingDecoder, Decoded, DecodingError, DecodingFormatError, Extensions, - Version -}; - -const N_CHANNELS: usize = 4; - -/// Output mode for the image data -#[derive(Clone, Copy, Debug, PartialEq)] -#[repr(u8)] -pub enum ColorOutput { - /// The decoder expands the image data to 32bit RGBA. - /// This affects: - /// - /// - The buffer buffer of the `Frame` returned by `Decoder::read_next_frame`. - /// - `Decoder::fill_buffer`, `Decoder::buffer_size` and `Decoder::line_length`. - RGBA = 0, - /// The decoder returns the raw indexed data. - Indexed = 1, -} - -#[derive(Clone, Debug)] -/// Memory limit in bytes. `MemoryLimit(0)` means -/// that there is no memory limit set. -pub struct MemoryLimit(pub u32); - -impl MemoryLimit { - /// Enforce no memory limit. - /// - /// If you intend to process images from unknown origins this is a potentially dangerous - /// constant to use, as your program could be vulnerable to decompression bombs. That is, - /// malicious images crafted specifically to require an enormous amount of memory to process - /// while having a disproportionately small file size. - /// - /// The risks for modern machines are a bit smaller as the dimensions of each frame can not - /// exceed `u32::MAX` (~4Gb) but this is still a significant amount of memory. - pub const NONE: MemoryLimit = MemoryLimit(0); - - fn buffer_size(&self, color: ColorOutput, width: u16, height: u16) -> Option<usize> { - let pixels = u32::from(width) * u32::from(height); - - let bytes_per_pixel = match color { - ColorOutput::Indexed => 1, - ColorOutput::RGBA => 4, - }; - - if self.0 > 0 && pixels > self.0 / bytes_per_pixel { - None - } else { - Some(pixels as usize * bytes_per_pixel as usize) - } - } -} - -/// Options for opening a GIF decoder. -#[derive(Clone, Debug)] -pub struct DecodeOptions { - memory_limit: MemoryLimit, - color_output: ColorOutput, - check_frame_consistency: bool, - check_for_end_code: bool, - allow_unknown_blocks: bool, -} - -impl DecodeOptions { - /// Creates a new decoder builder - pub fn new() -> DecodeOptions { - DecodeOptions { - memory_limit: MemoryLimit(50_000_000), // 50 MB - color_output: ColorOutput::Indexed, - check_frame_consistency: false, - check_for_end_code: false, - allow_unknown_blocks: false, - } - } - - /// Configure how color data is decoded. - pub fn set_color_output(&mut self, color: ColorOutput) { - self.color_output = color; - } - - /// Configure a memory limit for decoding. - pub fn set_memory_limit(&mut self, limit: MemoryLimit) { - self.memory_limit = limit; - } - - /// Configure if frames must be within the screen descriptor. - /// - /// The default is `false`. - /// - /// When turned on, all frame descriptors being read must fit within the screen descriptor or - /// otherwise an error is returned and the stream left in an unspecified state. - /// - /// When turned off, frames may be arbitrarily larger or offset in relation to the screen. Many - /// other decoder libraries handle this in highly divergent ways. This moves all checks to the - /// caller, for example to emulate a specific style. - pub fn check_frame_consistency(&mut self, check: bool) { - self.check_frame_consistency = check; - } - - /// Configure if LZW encoded blocks must end with a marker end code. - /// - /// The default is `false`. - /// - /// When turned on, all image data blocks—which are LZW encoded—must contain a special bit - /// sequence signalling the end of the data. LZW processing terminates when this code is - /// encountered. The specification states that it must be the last code output by the encoder - /// for an image. - /// - /// When turned off then image data blocks can simply end. Note that this might silently ignore - /// some bits of the last or second to last byte. - pub fn check_lzw_end_code(&mut self, check: bool) { - self.check_for_end_code = check; - } - - /// Configure if unknown blocks are allowed to be decoded. - /// - /// The default is `false`. - /// - /// When turned on, the decoder will allow unknown blocks to be in the - /// `BlockStart` position. - /// - /// When turned off, decoded block starts must mark an `Image`, `Extension`, - /// or `Trailer` block. Otherwise, the decoded image will return an error. - /// If an unknown block error is returned from decoding, enabling this - /// setting may allow for a further state of decoding on the next attempt. - pub fn allow_unknown_blocks(&mut self, check: bool) { - self.allow_unknown_blocks = check; - } - - /// Reads the logical screen descriptor including the global color palette - /// - /// Returns a `Decoder`. All decoder configuration has to be done beforehand. - pub fn read_info<R: Read>(self, r: R) -> Result<Decoder<R>, DecodingError> { - Decoder::with_no_init(r, StreamingDecoder::with_options(&self), self).init() - } -} - -struct ReadDecoder<R: Read> { - reader: io::BufReader<R>, - decoder: StreamingDecoder, - at_eof: bool -} - -impl<R: Read> ReadDecoder<R> { - fn decode_next(&mut self) -> Result<Option<Decoded>, DecodingError> { - while !self.at_eof { - let (consumed, result) = { - let buf = self.reader.fill_buf()?; - if buf.len() == 0 { - return Err(DecodingError::format( - "unexpected EOF" - )) - } - self.decoder.update(buf)? - }; - self.reader.consume(consumed); - match result { - Decoded::Nothing => (), - Decoded::BlockStart(Block::Trailer) => { - self.at_eof = true - }, - result => return Ok(unsafe{ - // FIXME: #6393 - Some(mem::transmute::<Decoded, Decoded>(result)) - }), - } - } - Ok(None) - } -} - -#[allow(dead_code)] -/// GIF decoder -pub struct Decoder<R: Read> { - decoder: ReadDecoder<R>, - color_output: ColorOutput, - memory_limit: MemoryLimit, - bg_color: Option<u8>, - global_palette: Option<Vec<u8>>, - current_frame: Frame<'static>, - buffer: Vec<u8>, -} - -impl<R> Decoder<R> where R: Read { - /// Create a new decoder with default options. - pub fn new(reader: R) -> Result<Self, DecodingError> { - DecodeOptions::new().read_info(reader) - } - - /// Return a builder that allows configuring limits etc. - pub fn build() -> DecodeOptions { - DecodeOptions::new() - } - - fn with_no_init(reader: R, decoder: StreamingDecoder, options: DecodeOptions) -> Decoder<R> { - Decoder { - decoder: ReadDecoder { - reader: io::BufReader::new(reader), - decoder, - at_eof: false - }, - bg_color: None, - global_palette: None, - buffer: Vec::with_capacity(32), - color_output: options.color_output, - memory_limit: options.memory_limit, - current_frame: Frame::default(), - } - } - - fn init(mut self) -> Result<Self, DecodingError> { - loop { - match self.decoder.decode_next()? { - Some(Decoded::BackgroundColor(bg_color)) => { - self.bg_color = Some(bg_color) - } - Some(Decoded::GlobalPalette(palette)) => { - self.global_palette = if palette.len() > 0 { - Some(palette) - } else { - None - }; - break - }, - Some(_) => { - // Unreachable since this loop exists after the global - // palette has been read. - unreachable!() - }, - None => return Err(DecodingError::format( - "file does not contain any image data" - )) - } - } - // If the background color is invalid, ignore it - if let Some(ref palette) = self.global_palette { - if self.bg_color.unwrap_or(0) as usize >= (palette.len() / PLTE_CHANNELS) { - self.bg_color = None; - } - } - Ok(self) - } - - /// Returns the next frame info - pub fn next_frame_info(&mut self) -> Result<Option<&Frame<'static>>, DecodingError> { - if !self.buffer.is_empty() { - // FIXME: Warn about discarding data? - self.buffer.clear(); - } - - loop { - match self.decoder.decode_next()? { - Some(Decoded::Frame(frame)) => { - self.current_frame = frame.clone(); - if frame.palette.is_none() && self.global_palette.is_none() { - return Err(DecodingError::format( - "no color table available for current frame" - )) - } - break - }, - Some(_) => (), - None => return Ok(None) - - } - } - Ok(Some(&self.current_frame)) - } - - /// Reads the next frame from the image. - /// - /// Do not call `Self::next_frame_info` beforehand. - /// Deinterlaces the result. - pub fn read_next_frame(&mut self) -> Result<Option<&Frame<'static>>, DecodingError> { - if let Some(frame) = self.next_frame_info()? { - let (width, height) = (frame.width, frame.height); - let pixel_bytes = self.memory_limit - .buffer_size(self.color_output, width, height) - .ok_or_else(|| { - DecodingError::format("image is too large to decode") - })?; - - debug_assert_eq!( - pixel_bytes, self.buffer_size(), - "Checked computation diverges from required buffer size" - ); - - let mut vec = vec![0; pixel_bytes]; - self.read_into_buffer(&mut vec)?; - self.current_frame.buffer = Cow::Owned(vec); - self.current_frame.interlaced = false; - Ok(Some(&self.current_frame)) - } else { - Ok(None) - } - } - - /// Reads the data of the current frame into a pre-allocated buffer. - /// - /// `Self::next_frame_info` needs to be called beforehand. - /// The length of `buf` must be at least `Self::buffer_size`. - /// Deinterlaces the result. - pub fn read_into_buffer(&mut self, buf: &mut [u8]) -> Result<(), DecodingError> { - if self.current_frame.interlaced { - let width = self.line_length(); - let height = self.current_frame.height as usize; - for row in (InterlaceIterator { len: height, next: 0, pass: 0 }) { - if !self.fill_buffer(&mut buf[row*width..][..width])? { - return Err(DecodingError::format("image truncated")) - } - } - } else { - let buf = &mut buf[..self.buffer_size()]; - if !self.fill_buffer(buf)? { - return Err(DecodingError::format("image truncated")) - } - }; - Ok(()) - } - - /// Reads data of the current frame into a pre-allocated buffer until the buffer has been - /// filled completely. - /// - /// `Self::next_frame_info` needs to be called beforehand. Returns `true` if the supplied - /// buffer could be filled completely. Should not be called after `false` had been returned. - pub fn fill_buffer(&mut self, mut buf: &mut [u8]) -> Result<bool, DecodingError> { - use self::ColorOutput::*; - const PLTE_CHANNELS: usize = 3; - macro_rules! handle_data( - ($data:expr) => { - match self.color_output { - RGBA => { - let transparent = self.current_frame.transparent; - let palette: &[u8] = match self.current_frame.palette { - Some(ref table) => &*table, - None => &*self.global_palette.as_ref().unwrap(), - }; - let len = cmp::min(buf.len()/N_CHANNELS, $data.len()); - for (rgba, &idx) in buf[..len*N_CHANNELS].chunks_mut(N_CHANNELS).zip($data.iter()) { - let plte_offset = PLTE_CHANNELS * idx as usize; - if palette.len() >= plte_offset + PLTE_CHANNELS { - let colors = &palette[plte_offset..]; - rgba[0] = colors[0]; - rgba[1] = colors[1]; - rgba[2] = colors[2]; - rgba[3] = if let Some(t) = transparent { - if t == idx { 0x00 } else { 0xFF } - } else { - 0xFF - } - } - } - (len, N_CHANNELS) - }, - Indexed => { - let len = cmp::min(buf.len(), $data.len()); - buf[..len].copy_from_slice(&$data[..len]); - (len, 1) - } - } - } - ); - let buf_len = self.buffer.len(); - if buf_len > 0 { - let (len, channels) = handle_data!(&self.buffer); - let _ = self.buffer.drain(..len); - buf = &mut buf[len*channels..]; - if buf.len() == 0 { - return Ok(true) - } - } - loop { - match self.decoder.decode_next()? { - Some(Decoded::Data(data)) => { - let (len, channels) = handle_data!(data); - buf = &mut buf[len*channels..]; // shorten buf - if buf.len() > 0 { - continue - } else if len < data.len() { - self.buffer.extend_from_slice(&data[len..]); - } - return Ok(true) - }, - Some(_) => return Ok(false), // make sure that no important result is missed - None => return Ok(false) - - } - } - } - - /// Output buffer size - pub fn buffer_size(&self) -> usize { - self.line_length() * self.current_frame.height as usize - } - - /// Line length of the current frame - pub fn line_length(&self) -> usize { - use self::ColorOutput::*; - match self.color_output { - RGBA => self.current_frame.width as usize * N_CHANNELS, - Indexed => self.current_frame.width as usize - } - } - - /// Returns the color palette relevant for the current (next) frame - pub fn palette(&self) -> Result<&[u8], DecodingError> { - // TODO prevent planic - Ok(match self.current_frame.palette { - Some(ref table) => &*table, - None => &*self.global_palette.as_ref().ok_or(DecodingError::format( - "no color table available for current frame" - ))?, - }) - } - - /// The global color palette - pub fn global_palette(&self) -> Option<&[u8]> { - self.global_palette.as_ref().map(|v| &**v) - } - - /// Width of the image - pub fn width(&self) -> u16 { - self.decoder.decoder.width() - } - - /// Height of the image - pub fn height(&self) -> u16 { - self.decoder.decoder.height() - } - - /// Index of the background color in the global palette - pub fn bg_color(&self) -> Option<usize> { - self.bg_color.map(|v| v as usize) - } -} - -struct InterlaceIterator { - len: usize, - next: usize, - pass: usize -} - -impl iter::Iterator for InterlaceIterator { - type Item = usize; - - fn next(&mut self) -> Option<Self::Item> { - if self.len == 0 || self.pass > 3 { - return None - } - let mut next = self.next + [8, 8, 4, 2][self.pass]; - while next >= self.len { - next = [4, 2, 1, 0][self.pass]; - self.pass += 1; - } - mem::swap(&mut next, &mut self.next); - Some(next) - } -} - -#[cfg(test)] -mod test { - use std::fs::File; - - use super::{Decoder, InterlaceIterator}; - - #[test] - fn test_simple_indexed() { - let mut decoder = Decoder::new(File::open("tests/samples/sample_1.gif").unwrap()).unwrap(); - let frame = decoder.read_next_frame().unwrap().unwrap(); - assert_eq!(&*frame.buffer, &[ - 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, - 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, - 1, 1, 1, 0, 0, 0, 0, 2, 2, 2, - 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, - 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, - 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, - 2, 2, 2, 2, 2, 1, 1, 1, 1, 1 - ][..]) - } - - #[test] - fn test_interlace_iterator() { - for &(len, expect) in &[ - (0, &[][..]), - (1, &[0][..]), - (2, &[0, 1][..]), - (3, &[0, 2, 1][..]), - (4, &[0, 2, 1, 3][..]), - (5, &[0, 4, 2, 1, 3][..]), - (6, &[0, 4, 2, 1, 3, 5][..]), - (7, &[0, 4, 2, 6, 1, 3, 5][..]), - (8, &[0, 4, 2, 6, 1, 3, 5, 7][..]), - (9, &[0, 8, 4, 2, 6, 1, 3, 5, 7][..]), - (10, &[0, 8, 4, 2, 6, 1, 3, 5, 7, 9][..]), - (11, &[0, 8, 4, 2, 6, 10, 1, 3, 5, 7, 9][..]), - (12, &[0, 8, 4, 2, 6, 10, 1, 3, 5, 7, 9, 11][..]), - (13, &[0, 8, 4, 12, 2, 6, 10, 1, 3, 5, 7, 9, 11][..]), - (14, &[0, 8, 4, 12, 2, 6, 10, 1, 3, 5, 7, 9, 11, 13][..]), - (15, &[0, 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13][..]), - (16, &[0, 8, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15][..]), - (17, &[0, 8, 16, 4, 12, 2, 6, 10, 14, 1, 3, 5, 7, 9, 11, 13, 15][..]), - ] { - let iter = InterlaceIterator { len: len, next: 0, pass: 0 }; - let lines = iter.collect::<Vec<_>>(); - assert_eq!(lines, expect); - } - } -} diff --git a/vendor/gif/src/traits.rs b/vendor/gif/src/traits.rs deleted file mode 100644 index 7fe326c..0000000 --- a/vendor/gif/src/traits.rs +++ /dev/null @@ -1,49 +0,0 @@ -//! Traits used in this library -use std::io; - -/// Writer extension to write little endian data -pub trait WriteBytesExt<T> { - /// Writes `T` to a bytes stream. Least significant byte first. - fn write_le(&mut self, n: T) -> io::Result<()>; - - /* - #[inline] - fn write_byte(&mut self, n: u8) -> io::Result<()> where Self: Write { - self.write_all(&[n]) - } - */ -} - -impl<W: io::Write + ?Sized> WriteBytesExt<u8> for W { - #[inline] - fn write_le(&mut self, n: u8) -> io::Result<()> { - self.write_all(&[n]) - - } -} - -impl<W: io::Write + ?Sized> WriteBytesExt<u16> for W { - #[inline] - fn write_le(&mut self, n: u16) -> io::Result<()> { - self.write_all(&[n as u8, (n>>8) as u8]) - - } -} - -impl<W: io::Write + ?Sized> WriteBytesExt<u32> for W { - #[inline] - fn write_le(&mut self, n: u32) -> io::Result<()> { - self.write_le(n as u16)?; - self.write_le((n >> 16) as u16) - - } -} - -impl<W: io::Write + ?Sized> WriteBytesExt<u64> for W { - #[inline] - fn write_le(&mut self, n: u64) -> io::Result<()> { - self.write_le(n as u32)?; - self.write_le((n >> 32) as u32) - - } -} |