aboutsummaryrefslogtreecommitdiff
path: root/vendor/image/src/codecs/bmp
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/image/src/codecs/bmp')
-rw-r--r--vendor/image/src/codecs/bmp/decoder.rs1483
-rw-r--r--vendor/image/src/codecs/bmp/encoder.rs388
-rw-r--r--vendor/image/src/codecs/bmp/mod.rs14
3 files changed, 0 insertions, 1885 deletions
diff --git a/vendor/image/src/codecs/bmp/decoder.rs b/vendor/image/src/codecs/bmp/decoder.rs
deleted file mode 100644
index 58c0650..0000000
--- a/vendor/image/src/codecs/bmp/decoder.rs
+++ /dev/null
@@ -1,1483 +0,0 @@
-use std::cmp::{self, Ordering};
-use std::convert::TryFrom;
-use std::io::{self, Cursor, Read, Seek, SeekFrom};
-use std::iter::{repeat, Iterator, Rev};
-use std::marker::PhantomData;
-use std::slice::ChunksMut;
-use std::{error, fmt, mem};
-
-use byteorder::{LittleEndian, ReadBytesExt};
-
-use crate::color::ColorType;
-use crate::error::{
- DecodingError, ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind,
-};
-use crate::image::{self, ImageDecoder, ImageDecoderRect, ImageFormat, Progress};
-
-const BITMAPCOREHEADER_SIZE: u32 = 12;
-const BITMAPINFOHEADER_SIZE: u32 = 40;
-const BITMAPV2HEADER_SIZE: u32 = 52;
-const BITMAPV3HEADER_SIZE: u32 = 56;
-const BITMAPV4HEADER_SIZE: u32 = 108;
-const BITMAPV5HEADER_SIZE: u32 = 124;
-
-static LOOKUP_TABLE_3_BIT_TO_8_BIT: [u8; 8] = [0, 36, 73, 109, 146, 182, 219, 255];
-static LOOKUP_TABLE_4_BIT_TO_8_BIT: [u8; 16] = [
- 0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255,
-];
-static LOOKUP_TABLE_5_BIT_TO_8_BIT: [u8; 32] = [
- 0, 8, 16, 25, 33, 41, 49, 58, 66, 74, 82, 90, 99, 107, 115, 123, 132, 140, 148, 156, 165, 173,
- 181, 189, 197, 206, 214, 222, 230, 239, 247, 255,
-];
-static LOOKUP_TABLE_6_BIT_TO_8_BIT: [u8; 64] = [
- 0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93,
- 97, 101, 105, 109, 113, 117, 121, 125, 130, 134, 138, 142, 146, 150, 154, 158, 162, 166, 170,
- 174, 178, 182, 186, 190, 194, 198, 202, 206, 210, 215, 219, 223, 227, 231, 235, 239, 243, 247,
- 251, 255,
-];
-
-static R5_G5_B5_COLOR_MASK: Bitfields = Bitfields {
- r: Bitfield { len: 5, shift: 10 },
- g: Bitfield { len: 5, shift: 5 },
- b: Bitfield { len: 5, shift: 0 },
- a: Bitfield { len: 0, shift: 0 },
-};
-const R8_G8_B8_COLOR_MASK: Bitfields = Bitfields {
- r: Bitfield { len: 8, shift: 24 },
- g: Bitfield { len: 8, shift: 16 },
- b: Bitfield { len: 8, shift: 8 },
- a: Bitfield { len: 0, shift: 0 },
-};
-const R8_G8_B8_A8_COLOR_MASK: Bitfields = Bitfields {
- r: Bitfield { len: 8, shift: 16 },
- g: Bitfield { len: 8, shift: 8 },
- b: Bitfield { len: 8, shift: 0 },
- a: Bitfield { len: 8, shift: 24 },
-};
-
-const RLE_ESCAPE: u8 = 0;
-const RLE_ESCAPE_EOL: u8 = 0;
-const RLE_ESCAPE_EOF: u8 = 1;
-const RLE_ESCAPE_DELTA: u8 = 2;
-
-/// The maximum width/height the decoder will process.
-const MAX_WIDTH_HEIGHT: i32 = 0xFFFF;
-
-#[derive(PartialEq, Copy, Clone)]
-enum ImageType {
- Palette,
- RGB16,
- RGB24,
- RGB32,
- RGBA32,
- RLE8,
- RLE4,
- Bitfields16,
- Bitfields32,
-}
-
-#[derive(PartialEq)]
-enum BMPHeaderType {
- Core,
- Info,
- V2,
- V3,
- V4,
- V5,
-}
-
-#[derive(PartialEq)]
-enum FormatFullBytes {
- RGB24,
- RGB32,
- RGBA32,
- Format888,
-}
-
-enum Chunker<'a> {
- FromTop(ChunksMut<'a, u8>),
- FromBottom(Rev<ChunksMut<'a, u8>>),
-}
-
-pub(crate) struct RowIterator<'a> {
- chunks: Chunker<'a>,
-}
-
-impl<'a> Iterator for RowIterator<'a> {
- type Item = &'a mut [u8];
-
- #[inline(always)]
- fn next(&mut self) -> Option<&'a mut [u8]> {
- match self.chunks {
- Chunker::FromTop(ref mut chunks) => chunks.next(),
- Chunker::FromBottom(ref mut chunks) => chunks.next(),
- }
- }
-}
-
-/// All errors that can occur when attempting to parse a BMP
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
-enum DecoderError {
- // Failed to decompress RLE data.
- CorruptRleData,
-
- /// The bitfield mask interleaves set and unset bits
- BitfieldMaskNonContiguous,
- /// Bitfield mask invalid (e.g. too long for specified type)
- BitfieldMaskInvalid,
- /// Bitfield (of the specified width – 16- or 32-bit) mask not present
- BitfieldMaskMissing(u32),
- /// Bitfield (of the specified width – 16- or 32-bit) masks not present
- BitfieldMasksMissing(u32),
-
- /// BMP's "BM" signature wrong or missing
- BmpSignatureInvalid,
- /// More than the exactly one allowed plane specified by the format
- MoreThanOnePlane,
- /// Invalid amount of bits per channel for the specified image type
- InvalidChannelWidth(ChannelWidthError, u16),
-
- /// The width is negative
- NegativeWidth(i32),
- /// One of the dimensions is larger than a soft limit
- ImageTooLarge(i32, i32),
- /// The height is `i32::min_value()`
- ///
- /// General negative heights specify top-down DIBs
- InvalidHeight,
-
- /// Specified image type is invalid for top-down BMPs (i.e. is compressed)
- ImageTypeInvalidForTopDown(u32),
- /// Image type not currently recognized by the decoder
- ImageTypeUnknown(u32),
-
- /// Bitmap header smaller than the core header
- HeaderTooSmall(u32),
-
- /// The palette is bigger than allowed by the bit count of the BMP
- PaletteSizeExceeded {
- colors_used: u32,
- bit_count: u16,
- },
-}
-
-impl fmt::Display for DecoderError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- DecoderError::CorruptRleData => f.write_str("Corrupt RLE data"),
- DecoderError::BitfieldMaskNonContiguous => f.write_str("Non-contiguous bitfield mask"),
- DecoderError::BitfieldMaskInvalid => f.write_str("Invalid bitfield mask"),
- DecoderError::BitfieldMaskMissing(bb) => {
- f.write_fmt(format_args!("Missing {}-bit bitfield mask", bb))
- }
- DecoderError::BitfieldMasksMissing(bb) => {
- f.write_fmt(format_args!("Missing {}-bit bitfield masks", bb))
- }
- DecoderError::BmpSignatureInvalid => f.write_str("BMP signature not found"),
- DecoderError::MoreThanOnePlane => f.write_str("More than one plane"),
- DecoderError::InvalidChannelWidth(tp, n) => {
- f.write_fmt(format_args!("Invalid channel bit count for {}: {}", tp, n))
- }
- DecoderError::NegativeWidth(w) => f.write_fmt(format_args!("Negative width ({})", w)),
- DecoderError::ImageTooLarge(w, h) => f.write_fmt(format_args!(
- "Image too large (one of ({}, {}) > soft limit of {})",
- w, h, MAX_WIDTH_HEIGHT
- )),
- DecoderError::InvalidHeight => f.write_str("Invalid height"),
- DecoderError::ImageTypeInvalidForTopDown(tp) => f.write_fmt(format_args!(
- "Invalid image type {} for top-down image.",
- tp
- )),
- DecoderError::ImageTypeUnknown(tp) => {
- f.write_fmt(format_args!("Unknown image compression type {}", tp))
- }
- DecoderError::HeaderTooSmall(s) => {
- f.write_fmt(format_args!("Bitmap header too small ({} bytes)", s))
- }
- DecoderError::PaletteSizeExceeded {
- colors_used,
- bit_count,
- } => f.write_fmt(format_args!(
- "Palette size {} exceeds maximum size for BMP with bit count of {}",
- colors_used, bit_count
- )),
- }
- }
-}
-
-impl From<DecoderError> for ImageError {
- fn from(e: DecoderError) -> ImageError {
- ImageError::Decoding(DecodingError::new(ImageFormat::Bmp.into(), e))
- }
-}
-
-impl error::Error for DecoderError {}
-
-/// Distinct image types whose saved channel width can be invalid
-#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
-enum ChannelWidthError {
- /// RGB
- Rgb,
- /// 8-bit run length encoding
- Rle8,
- /// 4-bit run length encoding
- Rle4,
- /// Bitfields (16- or 32-bit)
- Bitfields,
-}
-
-impl fmt::Display for ChannelWidthError {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- f.write_str(match self {
- ChannelWidthError::Rgb => "RGB",
- ChannelWidthError::Rle8 => "RLE8",
- ChannelWidthError::Rle4 => "RLE4",
- ChannelWidthError::Bitfields => "bitfields",
- })
- }
-}
-
-/// Convenience function to check if the combination of width, length and number of
-/// channels would result in a buffer that would overflow.
-fn check_for_overflow(width: i32, length: i32, channels: usize) -> ImageResult<()> {
- num_bytes(width, length, channels)
- .map(|_| ())
- .ok_or_else(|| {
- ImageError::Unsupported(UnsupportedError::from_format_and_kind(
- ImageFormat::Bmp.into(),
- UnsupportedErrorKind::GenericFeature(format!(
- "Image dimensions ({}x{} w/{} channels) are too large",
- width, length, channels
- )),
- ))
- })
-}
-
-/// Calculate how many many bytes a buffer holding a decoded image with these properties would
-/// require. Returns `None` if the buffer size would overflow or if one of the sizes are negative.
-fn num_bytes(width: i32, length: i32, channels: usize) -> Option<usize> {
- if width <= 0 || length <= 0 {
- None
- } else {
- match channels.checked_mul(width as usize) {
- Some(n) => n.checked_mul(length as usize),
- None => None,
- }
- }
-}
-
-/// Call the provided function on each row of the provided buffer, returning Err if the provided
-/// function returns an error, extends the buffer if it's not large enough.
-fn with_rows<F>(
- buffer: &mut [u8],
- width: i32,
- height: i32,
- channels: usize,
- top_down: bool,
- mut func: F,
-) -> io::Result<()>
-where
- F: FnMut(&mut [u8]) -> io::Result<()>,
-{
- // An overflow should already have been checked for when this is called,
- // though we check anyhow, as it somehow seems to increase performance slightly.
- let row_width = channels.checked_mul(width as usize).unwrap();
- let full_image_size = row_width.checked_mul(height as usize).unwrap();
- assert_eq!(buffer.len(), full_image_size);
-
- if !top_down {
- for row in buffer.chunks_mut(row_width).rev() {
- func(row)?;
- }
- } else {
- for row in buffer.chunks_mut(row_width) {
- func(row)?;
- }
- }
- Ok(())
-}
-
-fn set_8bit_pixel_run<'a, T: Iterator<Item = &'a u8>>(
- pixel_iter: &mut ChunksMut<u8>,
- palette: &[[u8; 3]],
- indices: T,
- n_pixels: usize,
-) -> bool {
- for idx in indices.take(n_pixels) {
- if let Some(pixel) = pixel_iter.next() {
- let rgb = palette[*idx as usize];
- pixel[0] = rgb[0];
- pixel[1] = rgb[1];
- pixel[2] = rgb[2];
- } else {
- return false;
- }
- }
- true
-}
-
-fn set_4bit_pixel_run<'a, T: Iterator<Item = &'a u8>>(
- pixel_iter: &mut ChunksMut<u8>,
- palette: &[[u8; 3]],
- indices: T,
- mut n_pixels: usize,
-) -> bool {
- for idx in indices {
- macro_rules! set_pixel {
- ($i:expr) => {
- if n_pixels == 0 {
- break;
- }
- if let Some(pixel) = pixel_iter.next() {
- let rgb = palette[$i as usize];
- pixel[0] = rgb[0];
- pixel[1] = rgb[1];
- pixel[2] = rgb[2];
- } else {
- return false;
- }
- n_pixels -= 1;
- };
- }
- set_pixel!(idx >> 4);
- set_pixel!(idx & 0xf);
- }
- true
-}
-
-#[rustfmt::skip]
-fn set_2bit_pixel_run<'a, T: Iterator<Item = &'a u8>>(
- pixel_iter: &mut ChunksMut<u8>,
- palette: &[[u8; 3]],
- indices: T,
- mut n_pixels: usize,
-) -> bool {
- for idx in indices {
- macro_rules! set_pixel {
- ($i:expr) => {
- if n_pixels == 0 {
- break;
- }
- if let Some(pixel) = pixel_iter.next() {
- let rgb = palette[$i as usize];
- pixel[0] = rgb[0];
- pixel[1] = rgb[1];
- pixel[2] = rgb[2];
- } else {
- return false;
- }
- n_pixels -= 1;
- };
- }
- set_pixel!((idx >> 6) & 0x3u8);
- set_pixel!((idx >> 4) & 0x3u8);
- set_pixel!((idx >> 2) & 0x3u8);
- set_pixel!( idx & 0x3u8);
- }
- true
-}
-
-fn set_1bit_pixel_run<'a, T: Iterator<Item = &'a u8>>(
- pixel_iter: &mut ChunksMut<u8>,
- palette: &[[u8; 3]],
- indices: T,
-) {
- for idx in indices {
- let mut bit = 0x80;
- loop {
- if let Some(pixel) = pixel_iter.next() {
- let rgb = palette[((idx & bit) != 0) as usize];
- pixel[0] = rgb[0];
- pixel[1] = rgb[1];
- pixel[2] = rgb[2];
- } else {
- return;
- }
-
- bit >>= 1;
- if bit == 0 {
- break;
- }
- }
- }
-}
-
-#[derive(PartialEq, Eq)]
-struct Bitfield {
- shift: u32,
- len: u32,
-}
-
-impl Bitfield {
- fn from_mask(mask: u32, max_len: u32) -> ImageResult<Bitfield> {
- if mask == 0 {
- return Ok(Bitfield { shift: 0, len: 0 });
- }
- let mut shift = mask.trailing_zeros();
- let mut len = (!(mask >> shift)).trailing_zeros();
- if len != mask.count_ones() {
- return Err(DecoderError::BitfieldMaskNonContiguous.into());
- }
- if len + shift > max_len {
- return Err(DecoderError::BitfieldMaskInvalid.into());
- }
- if len > 8 {
- shift += len - 8;
- len = 8;
- }
- Ok(Bitfield { shift, len })
- }
-
- fn read(&self, data: u32) -> u8 {
- let data = data >> self.shift;
- match self.len {
- 1 => ((data & 0b1) * 0xff) as u8,
- 2 => ((data & 0b11) * 0x55) as u8,
- 3 => LOOKUP_TABLE_3_BIT_TO_8_BIT[(data & 0b00_0111) as usize],
- 4 => LOOKUP_TABLE_4_BIT_TO_8_BIT[(data & 0b00_1111) as usize],
- 5 => LOOKUP_TABLE_5_BIT_TO_8_BIT[(data & 0b01_1111) as usize],
- 6 => LOOKUP_TABLE_6_BIT_TO_8_BIT[(data & 0b11_1111) as usize],
- 7 => ((data & 0x7f) << 1 | (data & 0x7f) >> 6) as u8,
- 8 => (data & 0xff) as u8,
- _ => panic!(),
- }
- }
-}
-
-#[derive(PartialEq, Eq)]
-struct Bitfields {
- r: Bitfield,
- g: Bitfield,
- b: Bitfield,
- a: Bitfield,
-}
-
-impl Bitfields {
- fn from_mask(
- r_mask: u32,
- g_mask: u32,
- b_mask: u32,
- a_mask: u32,
- max_len: u32,
- ) -> ImageResult<Bitfields> {
- let bitfields = Bitfields {
- r: Bitfield::from_mask(r_mask, max_len)?,
- g: Bitfield::from_mask(g_mask, max_len)?,
- b: Bitfield::from_mask(b_mask, max_len)?,
- a: Bitfield::from_mask(a_mask, max_len)?,
- };
- if bitfields.r.len == 0 || bitfields.g.len == 0 || bitfields.b.len == 0 {
- return Err(DecoderError::BitfieldMaskMissing(max_len).into());
- }
- Ok(bitfields)
- }
-}
-
-/// A bmp decoder
-pub struct BmpDecoder<R> {
- reader: R,
-
- bmp_header_type: BMPHeaderType,
- indexed_color: bool,
-
- width: i32,
- height: i32,
- data_offset: u64,
- top_down: bool,
- no_file_header: bool,
- add_alpha_channel: bool,
- has_loaded_metadata: bool,
- image_type: ImageType,
-
- bit_count: u16,
- colors_used: u32,
- palette: Option<Vec<[u8; 3]>>,
- bitfields: Option<Bitfields>,
-}
-
-enum RLEInsn {
- EndOfFile,
- EndOfRow,
- Delta(u8, u8),
- Absolute(u8, Vec<u8>),
- PixelRun(u8, u8),
-}
-
-impl<R: Read + Seek> BmpDecoder<R> {
- fn new_decoder(reader: R) -> BmpDecoder<R> {
- BmpDecoder {
- reader,
-
- bmp_header_type: BMPHeaderType::Info,
- indexed_color: false,
-
- width: 0,
- height: 0,
- data_offset: 0,
- top_down: false,
- no_file_header: false,
- add_alpha_channel: false,
- has_loaded_metadata: false,
- image_type: ImageType::Palette,
-
- bit_count: 0,
- colors_used: 0,
- palette: None,
- bitfields: None,
- }
- }
-
- /// Create a new decoder that decodes from the stream ```r```
- pub fn new(reader: R) -> ImageResult<BmpDecoder<R>> {
- let mut decoder = Self::new_decoder(reader);
- decoder.read_metadata()?;
- Ok(decoder)
- }
-
- /// Create a new decoder that decodes from the stream ```r``` without first
- /// reading a BITMAPFILEHEADER. This is useful for decoding the CF_DIB format
- /// directly from the Windows clipboard.
- pub fn new_without_file_header(reader: R) -> ImageResult<BmpDecoder<R>> {
- let mut decoder = Self::new_decoder(reader);
- decoder.no_file_header = true;
- decoder.read_metadata()?;
- Ok(decoder)
- }
-
- #[cfg(feature = "ico")]
- pub(crate) fn new_with_ico_format(reader: R) -> ImageResult<BmpDecoder<R>> {
- let mut decoder = Self::new_decoder(reader);
- decoder.read_metadata_in_ico_format()?;
- Ok(decoder)
- }
-
- /// If true, the palette in BMP does not apply to the image even if it is found.
- /// In other words, the output image is the indexed color.
- pub fn set_indexed_color(&mut self, indexed_color: bool) {
- self.indexed_color = indexed_color;
- }
-
- #[cfg(feature = "ico")]
- pub(crate) fn reader(&mut self) -> &mut R {
- &mut self.reader
- }
-
- fn read_file_header(&mut self) -> ImageResult<()> {
- if self.no_file_header {
- return Ok(());
- }
- let mut signature = [0; 2];
- self.reader.read_exact(&mut signature)?;
-
- if signature != b"BM"[..] {
- return Err(DecoderError::BmpSignatureInvalid.into());
- }
-
- // The next 8 bytes represent file size, followed the 4 reserved bytes
- // We're not interesting these values
- self.reader.read_u32::<LittleEndian>()?;
- self.reader.read_u32::<LittleEndian>()?;
-
- self.data_offset = u64::from(self.reader.read_u32::<LittleEndian>()?);
-
- Ok(())
- }
-
- /// Read BITMAPCOREHEADER https://msdn.microsoft.com/en-us/library/vs/alm/dd183372(v=vs.85).aspx
- ///
- /// returns Err if any of the values are invalid.
- fn read_bitmap_core_header(&mut self) -> ImageResult<()> {
- // As height/width values in BMP files with core headers are only 16 bits long,
- // they won't be larger than `MAX_WIDTH_HEIGHT`.
- self.width = i32::from(self.reader.read_u16::<LittleEndian>()?);
- self.height = i32::from(self.reader.read_u16::<LittleEndian>()?);
-
- check_for_overflow(self.width, self.height, self.num_channels())?;
-
- // Number of planes (format specifies that this should be 1).
- if self.reader.read_u16::<LittleEndian>()? != 1 {
- return Err(DecoderError::MoreThanOnePlane.into());
- }
-
- self.bit_count = self.reader.read_u16::<LittleEndian>()?;
- self.image_type = match self.bit_count {
- 1 | 4 | 8 => ImageType::Palette,
- 24 => ImageType::RGB24,
- _ => {
- return Err(DecoderError::InvalidChannelWidth(
- ChannelWidthError::Rgb,
- self.bit_count,
- )
- .into())
- }
- };
-
- Ok(())
- }
-
- /// Read BITMAPINFOHEADER https://msdn.microsoft.com/en-us/library/vs/alm/dd183376(v=vs.85).aspx
- /// or BITMAPV{2|3|4|5}HEADER.
- ///
- /// returns Err if any of the values are invalid.
- fn read_bitmap_info_header(&mut self) -> ImageResult<()> {
- self.width = self.reader.read_i32::<LittleEndian>()?;
- self.height = self.reader.read_i32::<LittleEndian>()?;
-
- // Width can not be negative
- if self.width < 0 {
- return Err(DecoderError::NegativeWidth(self.width).into());
- } else if self.width > MAX_WIDTH_HEIGHT || self.height > MAX_WIDTH_HEIGHT {
- // Limit very large image sizes to avoid OOM issues. Images with these sizes are
- // unlikely to be valid anyhow.
- return Err(DecoderError::ImageTooLarge(self.width, self.height).into());
- }
-
- if self.height == i32::min_value() {
- return Err(DecoderError::InvalidHeight.into());
- }
-
- // A negative height indicates a top-down DIB.
- if self.height < 0 {
- self.height *= -1;
- self.top_down = true;
- }
-
- check_for_overflow(self.width, self.height, self.num_channels())?;
-
- // Number of planes (format specifies that this should be 1).
- if self.reader.read_u16::<LittleEndian>()? != 1 {
- return Err(DecoderError::MoreThanOnePlane.into());
- }
-
- self.bit_count = self.reader.read_u16::<LittleEndian>()?;
- let image_type_u32 = self.reader.read_u32::<LittleEndian>()?;
-
- // Top-down dibs can not be compressed.
- if self.top_down && image_type_u32 != 0 && image_type_u32 != 3 {
- return Err(DecoderError::ImageTypeInvalidForTopDown(image_type_u32).into());
- }
- self.image_type = match image_type_u32 {
- 0 => match self.bit_count {
- 1 | 2 | 4 | 8 => ImageType::Palette,
- 16 => ImageType::RGB16,
- 24 => ImageType::RGB24,
- 32 if self.add_alpha_channel => ImageType::RGBA32,
- 32 => ImageType::RGB32,
- _ => {
- return Err(DecoderError::InvalidChannelWidth(
- ChannelWidthError::Rgb,
- self.bit_count,
- )
- .into())
- }
- },
- 1 => match self.bit_count {
- 8 => ImageType::RLE8,
- _ => {
- return Err(DecoderError::InvalidChannelWidth(
- ChannelWidthError::Rle8,
- self.bit_count,
- )
- .into())
- }
- },
- 2 => match self.bit_count {
- 4 => ImageType::RLE4,
- _ => {
- return Err(DecoderError::InvalidChannelWidth(
- ChannelWidthError::Rle4,
- self.bit_count,
- )
- .into())
- }
- },
- 3 => match self.bit_count {
- 16 => ImageType::Bitfields16,
- 32 => ImageType::Bitfields32,
- _ => {
- return Err(DecoderError::InvalidChannelWidth(
- ChannelWidthError::Bitfields,
- self.bit_count,
- )
- .into())
- }
- },
- 4 => {
- // JPEG compression is not implemented yet.
- return Err(ImageError::Unsupported(
- UnsupportedError::from_format_and_kind(
- ImageFormat::Bmp.into(),
- UnsupportedErrorKind::GenericFeature("JPEG compression".to_owned()),
- ),
- ));
- }
- 5 => {
- // PNG compression is not implemented yet.
- return Err(ImageError::Unsupported(
- UnsupportedError::from_format_and_kind(
- ImageFormat::Bmp.into(),
- UnsupportedErrorKind::GenericFeature("PNG compression".to_owned()),
- ),
- ));
- }
- 11 | 12 | 13 => {
- // CMYK types are not implemented yet.
- return Err(ImageError::Unsupported(
- UnsupportedError::from_format_and_kind(
- ImageFormat::Bmp.into(),
- UnsupportedErrorKind::GenericFeature("CMYK format".to_owned()),
- ),
- ));
- }
- _ => {
- // Unknown compression type.
- return Err(DecoderError::ImageTypeUnknown(image_type_u32).into());
- }
- };
-
- // The next 12 bytes represent data array size in bytes,
- // followed the horizontal and vertical printing resolutions
- // We will calculate the pixel array size using width & height of image
- // We're not interesting the horz or vert printing resolutions
- self.reader.read_u32::<LittleEndian>()?;
- self.reader.read_u32::<LittleEndian>()?;
- self.reader.read_u32::<LittleEndian>()?;
-
- self.colors_used = self.reader.read_u32::<LittleEndian>()?;
-
- // The next 4 bytes represent number of "important" colors
- // We're not interested in this value, so we'll skip it
- self.reader.read_u32::<LittleEndian>()?;
-
- Ok(())
- }
-
- fn read_bitmasks(&mut self) -> ImageResult<()> {
- let r_mask = self.reader.read_u32::<LittleEndian>()?;
- let g_mask = self.reader.read_u32::<LittleEndian>()?;
- let b_mask = self.reader.read_u32::<LittleEndian>()?;
-
- let a_mask = match self.bmp_header_type {
- BMPHeaderType::V3 | BMPHeaderType::V4 | BMPHeaderType::V5 => {
- self.reader.read_u32::<LittleEndian>()?
- }
- _ => 0,
- };
-
- self.bitfields = match self.image_type {
- ImageType::Bitfields16 => {
- Some(Bitfields::from_mask(r_mask, g_mask, b_mask, a_mask, 16)?)
- }
- ImageType::Bitfields32 => {
- Some(Bitfields::from_mask(r_mask, g_mask, b_mask, a_mask, 32)?)
- }
- _ => None,
- };
-
- if self.bitfields.is_some() && a_mask != 0 {
- self.add_alpha_channel = true;
- }
-
- Ok(())
- }
-
- fn read_metadata(&mut self) -> ImageResult<()> {
- if !self.has_loaded_metadata {
- self.read_file_header()?;
- let bmp_header_offset = self.reader.stream_position()?;
- let bmp_header_size = self.reader.read_u32::<LittleEndian>()?;
- let bmp_header_end = bmp_header_offset + u64::from(bmp_header_size);
-
- self.bmp_header_type = match bmp_header_size {
- BITMAPCOREHEADER_SIZE => BMPHeaderType::Core,
- BITMAPINFOHEADER_SIZE => BMPHeaderType::Info,
- BITMAPV2HEADER_SIZE => BMPHeaderType::V2,
- BITMAPV3HEADER_SIZE => BMPHeaderType::V3,
- BITMAPV4HEADER_SIZE => BMPHeaderType::V4,
- BITMAPV5HEADER_SIZE => BMPHeaderType::V5,
- _ if bmp_header_size < BITMAPCOREHEADER_SIZE => {
- // Size of any valid header types won't be smaller than core header type.
- return Err(DecoderError::HeaderTooSmall(bmp_header_size).into());
- }
- _ => {
- return Err(ImageError::Unsupported(
- UnsupportedError::from_format_and_kind(
- ImageFormat::Bmp.into(),
- UnsupportedErrorKind::GenericFeature(format!(
- "Unknown bitmap header type (size={})",
- bmp_header_size
- )),
- ),
- ))
- }
- };
-
- match self.bmp_header_type {
- BMPHeaderType::Core => {
- self.read_bitmap_core_header()?;
- }
- BMPHeaderType::Info
- | BMPHeaderType::V2
- | BMPHeaderType::V3
- | BMPHeaderType::V4
- | BMPHeaderType::V5 => {
- self.read_bitmap_info_header()?;
- }
- };
-
- match self.image_type {
- ImageType::Bitfields16 | ImageType::Bitfields32 => self.read_bitmasks()?,
- _ => {}
- };
-
- self.reader.seek(SeekFrom::Start(bmp_header_end))?;
-
- match self.image_type {
- ImageType::Palette | ImageType::RLE4 | ImageType::RLE8 => self.read_palette()?,
- _ => {}
- };
-
- if self.no_file_header {
- // Use the offset of the end of metadata instead of reading a BMP file header.
- self.data_offset = self.reader.stream_position()?;
- }
-
- self.has_loaded_metadata = true;
- }
- Ok(())
- }
-
- #[cfg(feature = "ico")]
- #[doc(hidden)]
- pub fn read_metadata_in_ico_format(&mut self) -> ImageResult<()> {
- self.no_file_header = true;
- self.add_alpha_channel = true;
- self.read_metadata()?;
-
- // The height field in an ICO file is doubled to account for the AND mask
- // (whether or not an AND mask is actually present).
- self.height /= 2;
- Ok(())
- }
-
- fn get_palette_size(&mut self) -> ImageResult<usize> {
- match self.colors_used {
- 0 => Ok(1 << self.bit_count),
- _ => {
- if self.colors_used > 1 << self.bit_count {
- return Err(DecoderError::PaletteSizeExceeded {
- colors_used: self.colors_used,
- bit_count: self.bit_count,
- }
- .into());
- }
- Ok(self.colors_used as usize)
- }
- }
- }
-
- fn bytes_per_color(&self) -> usize {
- match self.bmp_header_type {
- BMPHeaderType::Core => 3,
- _ => 4,
- }
- }
-
- fn read_palette(&mut self) -> ImageResult<()> {
- const MAX_PALETTE_SIZE: usize = 256; // Palette indices are u8.
-
- let bytes_per_color = self.bytes_per_color();
- let palette_size = self.get_palette_size()?;
- let max_length = MAX_PALETTE_SIZE * bytes_per_color;
-
- let length = palette_size * bytes_per_color;
- let mut buf = Vec::with_capacity(max_length);
-
- // Resize and read the palette entries to the buffer.
- // We limit the buffer to at most 256 colours to avoid any oom issues as
- // 8-bit images can't reference more than 256 indexes anyhow.
- buf.resize(cmp::min(length, max_length), 0);
- self.reader.by_ref().read_exact(&mut buf)?;
-
- // Allocate 256 entries even if palette_size is smaller, to prevent corrupt files from
- // causing an out-of-bounds array access.
- match length.cmp(&max_length) {
- Ordering::Greater => {
- self.reader
- .seek(SeekFrom::Current((length - max_length) as i64))?;
- }
- Ordering::Less => buf.resize(max_length, 0),
- Ordering::Equal => (),
- }
-
- let p: Vec<[u8; 3]> = (0..MAX_PALETTE_SIZE)
- .map(|i| {
- let b = buf[bytes_per_color * i];
- let g = buf[bytes_per_color * i + 1];
- let r = buf[bytes_per_color * i + 2];
- [r, g, b]
- })
- .collect();
-
- self.palette = Some(p);
-
- Ok(())
- }
-
- /// Get the palette that is embedded in the BMP image, if any.
- pub fn get_palette(&self) -> Option<&[[u8; 3]]> {
- self.palette.as_ref().map(|vec| &vec[..])
- }
-
- fn num_channels(&self) -> usize {
- if self.indexed_color {
- 1
- } else if self.add_alpha_channel {
- 4
- } else {
- 3
- }
- }
-
- fn rows<'a>(&self, pixel_data: &'a mut [u8]) -> RowIterator<'a> {
- let stride = self.width as usize * self.num_channels();
- if self.top_down {
- RowIterator {
- chunks: Chunker::FromTop(pixel_data.chunks_mut(stride)),
- }
- } else {
- RowIterator {
- chunks: Chunker::FromBottom(pixel_data.chunks_mut(stride).rev()),
- }
- }
- }
-
- fn read_palettized_pixel_data(&mut self, buf: &mut [u8]) -> ImageResult<()> {
- let num_channels = self.num_channels();
- let row_byte_length = ((i32::from(self.bit_count) * self.width + 31) / 32 * 4) as usize;
- let mut indices = vec![0; row_byte_length];
- let palette = self.palette.as_ref().unwrap();
- let bit_count = self.bit_count;
- let reader = &mut self.reader;
- let width = self.width as usize;
- let skip_palette = self.indexed_color;
-
- reader.seek(SeekFrom::Start(self.data_offset))?;
-
- if num_channels == 4 {
- buf.chunks_exact_mut(4).for_each(|c| c[3] = 0xFF);
- }
-
- with_rows(
- buf,
- self.width,
- self.height,
- num_channels,
- self.top_down,
- |row| {
- reader.read_exact(&mut indices)?;
- if skip_palette {
- row.clone_from_slice(&indices[0..width]);
- } else {
- let mut pixel_iter = row.chunks_mut(num_channels);
- match bit_count {
- 1 => {
- set_1bit_pixel_run(&mut pixel_iter, palette, indices.iter());
- }
- 2 => {
- set_2bit_pixel_run(&mut pixel_iter, palette, indices.iter(), width);
- }
- 4 => {
- set_4bit_pixel_run(&mut pixel_iter, palette, indices.iter(), width);
- }
- 8 => {
- set_8bit_pixel_run(&mut pixel_iter, palette, indices.iter(), width);
- }
- _ => panic!(),
- };
- }
- Ok(())
- },
- )?;
-
- Ok(())
- }
-
- fn read_16_bit_pixel_data(
- &mut self,
- buf: &mut [u8],
- bitfields: Option<&Bitfields>,
- ) -> ImageResult<()> {
- let num_channels = self.num_channels();
- let row_padding_len = self.width as usize % 2 * 2;
- let row_padding = &mut [0; 2][..row_padding_len];
- let bitfields = match bitfields {
- Some(b) => b,
- None => self.bitfields.as_ref().unwrap(),
- };
- let reader = &mut self.reader;
-
- reader.seek(SeekFrom::Start(self.data_offset))?;
-
- with_rows(
- buf,
- self.width,
- self.height,
- num_channels,
- self.top_down,
- |row| {
- for pixel in row.chunks_mut(num_channels) {
- let data = u32::from(reader.read_u16::<LittleEndian>()?);
-
- pixel[0] = bitfields.r.read(data);
- pixel[1] = bitfields.g.read(data);
- pixel[2] = bitfields.b.read(data);
- if num_channels == 4 {
- if bitfields.a.len != 0 {
- pixel[3] = bitfields.a.read(data);
- } else {
- pixel[3] = 0xFF;
- }
- }
- }
- reader.read_exact(row_padding)
- },
- )?;
-
- Ok(())
- }
-
- /// Read image data from a reader in 32-bit formats that use bitfields.
- fn read_32_bit_pixel_data(&mut self, buf: &mut [u8]) -> ImageResult<()> {
- let num_channels = self.num_channels();
-
- let bitfields = self.bitfields.as_ref().unwrap();
-
- let reader = &mut self.reader;
- reader.seek(SeekFrom::Start(self.data_offset))?;
-
- with_rows(
- buf,
- self.width,
- self.height,
- num_channels,
- self.top_down,
- |row| {
- for pixel in row.chunks_mut(num_channels) {
- let data = reader.read_u32::<LittleEndian>()?;
-
- pixel[0] = bitfields.r.read(data);
- pixel[1] = bitfields.g.read(data);
- pixel[2] = bitfields.b.read(data);
- if num_channels == 4 {
- if bitfields.a.len != 0 {
- pixel[3] = bitfields.a.read(data);
- } else {
- pixel[3] = 0xff;
- }
- }
- }
- Ok(())
- },
- )?;
-
- Ok(())
- }
-
- /// Read image data from a reader where the colours are stored as 8-bit values (24 or 32-bit).
- fn read_full_byte_pixel_data(
- &mut self,
- buf: &mut [u8],
- format: &FormatFullBytes,
- ) -> ImageResult<()> {
- let num_channels = self.num_channels();
- let row_padding_len = match *format {
- FormatFullBytes::RGB24 => (4 - (self.width as usize * 3) % 4) % 4,
- _ => 0,
- };
- let row_padding = &mut [0; 4][..row_padding_len];
-
- self.reader.seek(SeekFrom::Start(self.data_offset))?;
-
- let reader = &mut self.reader;
-
- with_rows(
- buf,
- self.width,
- self.height,
- num_channels,
- self.top_down,
- |row| {
- for pixel in row.chunks_mut(num_channels) {
- if *format == FormatFullBytes::Format888 {
- reader.read_u8()?;
- }
-
- // Read the colour values (b, g, r).
- // Reading 3 bytes and reversing them is significantly faster than reading one
- // at a time.
- reader.read_exact(&mut pixel[0..3])?;
- pixel[0..3].reverse();
-
- if *format == FormatFullBytes::RGB32 {
- reader.read_u8()?;
- }
-
- // Read the alpha channel if present
- if *format == FormatFullBytes::RGBA32 {
- reader.read_exact(&mut pixel[3..4])?;
- } else if num_channels == 4 {
- pixel[3] = 0xFF;
- }
- }
- reader.read_exact(row_padding)
- },
- )?;
-
- Ok(())
- }
-
- fn read_rle_data(&mut self, buf: &mut [u8], image_type: ImageType) -> ImageResult<()> {
- // Seek to the start of the actual image data.
- self.reader.seek(SeekFrom::Start(self.data_offset))?;
-
- let num_channels = self.num_channels();
- let p = self.palette.as_ref().unwrap();
-
- // Handling deltas in the RLE scheme means that we need to manually
- // iterate through rows and pixels. Even if we didn't have to handle
- // deltas, we have to ensure that a single runlength doesn't straddle
- // two rows.
- let mut row_iter = self.rows(buf);
-
- while let Some(row) = row_iter.next() {
- let mut pixel_iter = row.chunks_mut(num_channels);
-
- let mut x = 0;
- loop {
- let instruction = {
- let control_byte = self.reader.read_u8()?;
- match control_byte {
- RLE_ESCAPE => {
- let op = self.reader.read_u8()?;
-
- match op {
- RLE_ESCAPE_EOL => RLEInsn::EndOfRow,
- RLE_ESCAPE_EOF => RLEInsn::EndOfFile,
- RLE_ESCAPE_DELTA => {
- let xdelta = self.reader.read_u8()?;
- let ydelta = self.reader.read_u8()?;
- RLEInsn::Delta(xdelta, ydelta)
- }
- _ => {
- let mut length = op as usize;
- if self.image_type == ImageType::RLE4 {
- length = (length + 1) / 2;
- }
- length += length & 1;
- let mut buffer = vec![0; length];
- self.reader.read_exact(&mut buffer)?;
- RLEInsn::Absolute(op, buffer)
- }
- }
- }
- _ => {
- let palette_index = self.reader.read_u8()?;
- RLEInsn::PixelRun(control_byte, palette_index)
- }
- }
- };
-
- match instruction {
- RLEInsn::EndOfFile => {
- pixel_iter.for_each(|p| p.fill(0));
- row_iter.for_each(|r| r.fill(0));
- return Ok(());
- }
- RLEInsn::EndOfRow => {
- pixel_iter.for_each(|p| p.fill(0));
- break;
- }
- RLEInsn::Delta(x_delta, y_delta) => {
- // The msdn site on bitmap compression doesn't specify
- // what happens to the values skipped when encountering
- // a delta code, however IE and the windows image
- // preview seems to replace them with black pixels,
- // so we stick to that.
-
- if y_delta > 0 {
- // Zero out the remainder of the current row.
- pixel_iter.for_each(|p| p.fill(0));
-
- // If any full rows are skipped, zero them out.
- for _ in 1..y_delta {
- let row = row_iter.next().ok_or(DecoderError::CorruptRleData)?;
- row.fill(0);
- }
-
- // Set the pixel iterator to the start of the next row.
- pixel_iter = row_iter
- .next()
- .ok_or(DecoderError::CorruptRleData)?
- .chunks_mut(num_channels);
-
- // Zero out the pixels up to the current point in the row.
- for _ in 0..x {
- pixel_iter
- .next()
- .ok_or(DecoderError::CorruptRleData)?
- .fill(0);
- }
- }
-
- for _ in 0..x_delta {
- let pixel = pixel_iter.next().ok_or(DecoderError::CorruptRleData)?;
- pixel.fill(0);
- }
- x += x_delta as usize;
- }
- RLEInsn::Absolute(length, indices) => {
- // Absolute mode cannot span rows, so if we run
- // out of pixels to process, we should stop
- // processing the image.
- match image_type {
- ImageType::RLE8 => {
- if !set_8bit_pixel_run(
- &mut pixel_iter,
- p,
- indices.iter(),
- length as usize,
- ) {
- return Err(DecoderError::CorruptRleData.into());
- }
- }
- ImageType::RLE4 => {
- if !set_4bit_pixel_run(
- &mut pixel_iter,
- p,
- indices.iter(),
- length as usize,
- ) {
- return Err(DecoderError::CorruptRleData.into());
- }
- }
- _ => unreachable!(),
- }
- x += length as usize;
- }
- RLEInsn::PixelRun(n_pixels, palette_index) => {
- // A pixel run isn't allowed to span rows, but we
- // simply continue on to the next row if we run
- // out of pixels to set.
- match image_type {
- ImageType::RLE8 => {
- if !set_8bit_pixel_run(
- &mut pixel_iter,
- p,
- repeat(&palette_index),
- n_pixels as usize,
- ) {
- return Err(DecoderError::CorruptRleData.into());
- }
- }
- ImageType::RLE4 => {
- if !set_4bit_pixel_run(
- &mut pixel_iter,
- p,
- repeat(&palette_index),
- n_pixels as usize,
- ) {
- return Err(DecoderError::CorruptRleData.into());
- }
- }
- _ => unreachable!(),
- }
- x += n_pixels as usize;
- }
- }
- }
- }
-
- Ok(())
- }
-
- /// Read the actual data of the image. This function is deliberately not public because it
- /// cannot be called multiple times without seeking back the underlying reader in between.
- pub(crate) fn read_image_data(&mut self, buf: &mut [u8]) -> ImageResult<()> {
- match self.image_type {
- ImageType::Palette => self.read_palettized_pixel_data(buf),
- ImageType::RGB16 => self.read_16_bit_pixel_data(buf, Some(&R5_G5_B5_COLOR_MASK)),
- ImageType::RGB24 => self.read_full_byte_pixel_data(buf, &FormatFullBytes::RGB24),
- ImageType::RGB32 => self.read_full_byte_pixel_data(buf, &FormatFullBytes::RGB32),
- ImageType::RGBA32 => self.read_full_byte_pixel_data(buf, &FormatFullBytes::RGBA32),
- ImageType::RLE8 => self.read_rle_data(buf, ImageType::RLE8),
- ImageType::RLE4 => self.read_rle_data(buf, ImageType::RLE4),
- ImageType::Bitfields16 => match self.bitfields {
- Some(_) => self.read_16_bit_pixel_data(buf, None),
- None => Err(DecoderError::BitfieldMasksMissing(16).into()),
- },
- ImageType::Bitfields32 => match self.bitfields {
- Some(R8_G8_B8_COLOR_MASK) => {
- self.read_full_byte_pixel_data(buf, &FormatFullBytes::Format888)
- }
- Some(R8_G8_B8_A8_COLOR_MASK) => {
- self.read_full_byte_pixel_data(buf, &FormatFullBytes::RGBA32)
- }
- Some(_) => self.read_32_bit_pixel_data(buf),
- None => Err(DecoderError::BitfieldMasksMissing(32).into()),
- },
- }
- }
-}
-
-/// Wrapper struct around a `Cursor<Vec<u8>>`
-pub struct BmpReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
-impl<R> Read for BmpReader<R> {
- fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
- self.0.read(buf)
- }
- fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
- if self.0.position() == 0 && buf.is_empty() {
- mem::swap(buf, self.0.get_mut());
- Ok(buf.len())
- } else {
- self.0.read_to_end(buf)
- }
- }
-}
-
-impl<'a, R: 'a + Read + Seek> ImageDecoder<'a> for BmpDecoder<R> {
- type Reader = BmpReader<R>;
-
- fn dimensions(&self) -> (u32, u32) {
- (self.width as u32, self.height as u32)
- }
-
- fn color_type(&self) -> ColorType {
- if self.indexed_color {
- ColorType::L8
- } else if self.add_alpha_channel {
- ColorType::Rgba8
- } else {
- ColorType::Rgb8
- }
- }
-
- fn into_reader(self) -> ImageResult<Self::Reader> {
- Ok(BmpReader(
- Cursor::new(image::decoder_to_vec(self)?),
- PhantomData,
- ))
- }
-
- fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> {
- assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes()));
- self.read_image_data(buf)
- }
-}
-
-impl<'a, R: 'a + Read + Seek> ImageDecoderRect<'a> for BmpDecoder<R> {
- fn read_rect_with_progress<F: Fn(Progress)>(
- &mut self,
- x: u32,
- y: u32,
- width: u32,
- height: u32,
- buf: &mut [u8],
- progress_callback: F,
- ) -> ImageResult<()> {
- let start = self.reader.stream_position()?;
- image::load_rect(
- x,
- y,
- width,
- height,
- buf,
- progress_callback,
- self,
- |_, _| Ok(()),
- |s, buf| s.read_image_data(buf),
- )?;
- self.reader.seek(SeekFrom::Start(start))?;
- Ok(())
- }
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
-
- #[test]
- fn test_bitfield_len() {
- for len in 1..9 {
- let bitfield = Bitfield { shift: 0, len };
- for i in 0..(1 << len) {
- let read = bitfield.read(i);
- let calc = (i as f64 / ((1 << len) - 1) as f64 * 255f64).round() as u8;
- if read != calc {
- println!("len:{} i:{} read:{} calc:{}", len, i, read, calc);
- }
- assert_eq!(read, calc);
- }
- }
- }
-
- #[test]
- fn read_rect() {
- let f = std::fs::File::open("tests/images/bmp/images/Core_8_Bit.bmp").unwrap();
- let mut decoder = super::BmpDecoder::new(f).unwrap();
-
- let mut buf: Vec<u8> = vec![0; 8 * 8 * 3];
- decoder.read_rect(0, 0, 8, 8, &mut *buf).unwrap();
- }
-
- #[test]
- fn read_rle_too_short() {
- let data = vec![
- 0x42, 0x4d, 0x04, 0xee, 0xfe, 0xff, 0xff, 0x10, 0xff, 0x00, 0x04, 0x00, 0x00, 0x00,
- 0x7c, 0x00, 0x00, 0x00, 0x0c, 0x41, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x01, 0x00,
- 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x21,
- 0xff, 0x00, 0x66, 0x61, 0x72, 0x62, 0x66, 0x65, 0x6c, 0x64, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xff, 0xd8, 0xff, 0x00, 0x00, 0x19, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0xff, 0x00, 0x00, 0x00,
- 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
- 0x00, 0x00, 0x00, 0x2d, 0x31, 0x31, 0x35, 0x36, 0x00, 0xff, 0x00, 0x00, 0x52, 0x3a,
- 0x37, 0x30, 0x7e, 0x71, 0x63, 0x91, 0x5a, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x35, 0x37, 0x00, 0xff, 0x00, 0x00, 0x52,
- 0x3a, 0x37, 0x30, 0x7e, 0x71, 0x63, 0x91, 0x5a, 0x04, 0x05, 0x3c, 0x00, 0x00, 0x11,
- 0x00, 0x5d, 0x7a, 0x82, 0xb7, 0xca, 0x2d, 0x31, 0xff, 0xff, 0xc7, 0x95, 0x33, 0x2e,
- 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x66, 0x00, 0x4d,
- 0x4d, 0x00, 0x2a, 0x00,
- ];
-
- let decoder = BmpDecoder::new(Cursor::new(&data)).unwrap();
- let mut buf = vec![0; usize::try_from(decoder.total_bytes()).unwrap()];
- assert!(decoder.read_image(&mut buf).is_ok());
- }
-
- #[test]
- fn test_no_header() {
- let tests = [
- "Info_R8_G8_B8.bmp",
- "Info_A8_R8_G8_B8.bmp",
- "Info_8_Bit.bmp",
- "Info_4_Bit.bmp",
- "Info_1_Bit.bmp",
- ];
-
- for name in &tests {
- let path = format!("tests/images/bmp/images/{name}");
- let ref_img = crate::open(&path).unwrap();
- let mut data = std::fs::read(&path).unwrap();
- // skip the BITMAPFILEHEADER
- let slice = &mut data[14..];
- let decoder = BmpDecoder::new_without_file_header(Cursor::new(slice)).unwrap();
- let no_hdr_img = crate::DynamicImage::from_decoder(decoder).unwrap();
- assert_eq!(ref_img, no_hdr_img);
- }
- }
-}
diff --git a/vendor/image/src/codecs/bmp/encoder.rs b/vendor/image/src/codecs/bmp/encoder.rs
deleted file mode 100644
index c90c063..0000000
--- a/vendor/image/src/codecs/bmp/encoder.rs
+++ /dev/null
@@ -1,388 +0,0 @@
-use byteorder::{LittleEndian, WriteBytesExt};
-use std::io::{self, Write};
-
-use crate::error::{
- EncodingError, ImageError, ImageFormatHint, ImageResult, ParameterError, ParameterErrorKind,
-};
-use crate::image::ImageEncoder;
-use crate::{color, ImageFormat};
-
-const BITMAPFILEHEADER_SIZE: u32 = 14;
-const BITMAPINFOHEADER_SIZE: u32 = 40;
-const BITMAPV4HEADER_SIZE: u32 = 108;
-
-/// The representation of a BMP encoder.
-pub struct BmpEncoder<'a, W: 'a> {
- writer: &'a mut W,
-}
-
-impl<'a, W: Write + 'a> BmpEncoder<'a, W> {
- /// Create a new encoder that writes its output to ```w```.
- pub fn new(w: &'a mut W) -> Self {
- BmpEncoder { writer: w }
- }
-
- /// Encodes the image ```image```
- /// that has dimensions ```width``` and ```height```
- /// and ```ColorType``` ```c```.
- pub fn encode(
- &mut self,
- image: &[u8],
- width: u32,
- height: u32,
- c: color::ColorType,
- ) -> ImageResult<()> {
- self.encode_with_palette(image, width, height, c, None)
- }
-
- /// Same as ```encode```, but allow a palette to be passed in.
- /// The ```palette``` is ignored for color types other than Luma/Luma-with-alpha.
- pub fn encode_with_palette(
- &mut self,
- image: &[u8],
- width: u32,
- height: u32,
- c: color::ColorType,
- palette: Option<&[[u8; 3]]>,
- ) -> ImageResult<()> {
- if palette.is_some() && c != color::ColorType::L8 && c != color::ColorType::La8 {
- return Err(ImageError::IoError(io::Error::new(
- io::ErrorKind::InvalidInput,
- format!(
- "Unsupported color type {:?} when using a non-empty palette. Supported types: Gray(8), GrayA(8).",
- c
- ),
- )));
- }
-
- let bmp_header_size = BITMAPFILEHEADER_SIZE;
-
- let (dib_header_size, written_pixel_size, palette_color_count) =
- get_pixel_info(c, palette)?;
- let row_pad_size = (4 - (width * written_pixel_size) % 4) % 4; // each row must be padded to a multiple of 4 bytes
- let image_size = width
- .checked_mul(height)
- .and_then(|v| v.checked_mul(written_pixel_size))
- .and_then(|v| v.checked_add(height * row_pad_size))
- .ok_or_else(|| {
- ImageError::Parameter(ParameterError::from_kind(
- ParameterErrorKind::DimensionMismatch,
- ))
- })?;
- let palette_size = palette_color_count * 4; // all palette colors are BGRA
- let file_size = bmp_header_size
- .checked_add(dib_header_size)
- .and_then(|v| v.checked_add(palette_size))
- .and_then(|v| v.checked_add(image_size))
- .ok_or_else(|| {
- ImageError::Encoding(EncodingError::new(
- ImageFormatHint::Exact(ImageFormat::Bmp),
- "calculated BMP header size larger than 2^32",
- ))
- })?;
-
- // write BMP header
- self.writer.write_u8(b'B')?;
- self.writer.write_u8(b'M')?;
- self.writer.write_u32::<LittleEndian>(file_size)?; // file size
- self.writer.write_u16::<LittleEndian>(0)?; // reserved 1
- self.writer.write_u16::<LittleEndian>(0)?; // reserved 2
- self.writer
- .write_u32::<LittleEndian>(bmp_header_size + dib_header_size + palette_size)?; // image data offset
-
- // write DIB header
- self.writer.write_u32::<LittleEndian>(dib_header_size)?;
- self.writer.write_i32::<LittleEndian>(width as i32)?;
- self.writer.write_i32::<LittleEndian>(height as i32)?;
- self.writer.write_u16::<LittleEndian>(1)?; // color planes
- self.writer
- .write_u16::<LittleEndian>((written_pixel_size * 8) as u16)?; // bits per pixel
- if dib_header_size >= BITMAPV4HEADER_SIZE {
- // Assume BGRA32
- self.writer.write_u32::<LittleEndian>(3)?; // compression method - bitfields
- } else {
- self.writer.write_u32::<LittleEndian>(0)?; // compression method - no compression
- }
- self.writer.write_u32::<LittleEndian>(image_size)?;
- self.writer.write_i32::<LittleEndian>(0)?; // horizontal ppm
- self.writer.write_i32::<LittleEndian>(0)?; // vertical ppm
- self.writer.write_u32::<LittleEndian>(palette_color_count)?;
- self.writer.write_u32::<LittleEndian>(0)?; // all colors are important
- if dib_header_size >= BITMAPV4HEADER_SIZE {
- // Assume BGRA32
- self.writer.write_u32::<LittleEndian>(0xff << 16)?; // red mask
- self.writer.write_u32::<LittleEndian>(0xff << 8)?; // green mask
- self.writer.write_u32::<LittleEndian>(0xff)?; // blue mask
- self.writer.write_u32::<LittleEndian>(0xff << 24)?; // alpha mask
- self.writer.write_u32::<LittleEndian>(0x73524742)?; // colorspace - sRGB
-
- // endpoints (3x3) and gamma (3)
- for _ in 0..12 {
- self.writer.write_u32::<LittleEndian>(0)?;
- }
- }
-
- // write image data
- match c {
- color::ColorType::Rgb8 => self.encode_rgb(image, width, height, row_pad_size, 3)?,
- color::ColorType::Rgba8 => self.encode_rgba(image, width, height, row_pad_size, 4)?,
- color::ColorType::L8 => {
- self.encode_gray(image, width, height, row_pad_size, 1, palette)?
- }
- color::ColorType::La8 => {
- self.encode_gray(image, width, height, row_pad_size, 2, palette)?
- }
- _ => {
- return Err(ImageError::IoError(io::Error::new(
- io::ErrorKind::InvalidInput,
- &get_unsupported_error_message(c)[..],
- )))
- }
- }
-
- Ok(())
- }
-
- fn encode_rgb(
- &mut self,
- image: &[u8],
- width: u32,
- height: u32,
- row_pad_size: u32,
- bytes_per_pixel: u32,
- ) -> io::Result<()> {
- let width = width as usize;
- let height = height as usize;
- let x_stride = bytes_per_pixel as usize;
- let y_stride = width * x_stride;
- for row in (0..height).rev() {
- // from the bottom up
- let row_start = row * y_stride;
- for px in image[row_start..][..y_stride].chunks_exact(x_stride) {
- let r = px[0];
- let g = px[1];
- let b = px[2];
- // written as BGR
- self.writer.write_all(&[b, g, r])?;
- }
- self.write_row_pad(row_pad_size)?;
- }
-
- Ok(())
- }
-
- fn encode_rgba(
- &mut self,
- image: &[u8],
- width: u32,
- height: u32,
- row_pad_size: u32,
- bytes_per_pixel: u32,
- ) -> io::Result<()> {
- let width = width as usize;
- let height = height as usize;
- let x_stride = bytes_per_pixel as usize;
- let y_stride = width * x_stride;
- for row in (0..height).rev() {
- // from the bottom up
- let row_start = row * y_stride;
- for px in image[row_start..][..y_stride].chunks_exact(x_stride) {
- let r = px[0];
- let g = px[1];
- let b = px[2];
- let a = px[3];
- // written as BGRA
- self.writer.write_all(&[b, g, r, a])?;
- }
- self.write_row_pad(row_pad_size)?;
- }
-
- Ok(())
- }
-
- fn encode_gray(
- &mut self,
- image: &[u8],
- width: u32,
- height: u32,
- row_pad_size: u32,
- bytes_per_pixel: u32,
- palette: Option<&[[u8; 3]]>,
- ) -> io::Result<()> {
- // write grayscale palette
- if let Some(palette) = palette {
- for item in palette {
- // each color is written as BGRA, where A is always 0
- self.writer.write_all(&[item[2], item[1], item[0], 0])?;
- }
- } else {
- for val in 0u8..=255 {
- // each color is written as BGRA, where A is always 0 and since only grayscale is being written, B = G = R = index
- self.writer.write_all(&[val, val, val, 0])?;
- }
- }
-
- // write image data
- let x_stride = bytes_per_pixel;
- let y_stride = width * x_stride;
- for row in (0..height).rev() {
- // from the bottom up
- let row_start = row * y_stride;
- for col in 0..width {
- let pixel_start = (row_start + (col * x_stride)) as usize;
- // color value is equal to the palette index
- self.writer.write_u8(image[pixel_start])?;
- // alpha is never written as it's not widely supported
- }
-
- self.write_row_pad(row_pad_size)?;
- }
-
- Ok(())
- }
-
- fn write_row_pad(&mut self, row_pad_size: u32) -> io::Result<()> {
- for _ in 0..row_pad_size {
- self.writer.write_u8(0)?;
- }
-
- Ok(())
- }
-}
-
-impl<'a, W: Write> ImageEncoder for BmpEncoder<'a, W> {
- fn write_image(
- mut self,
- buf: &[u8],
- width: u32,
- height: u32,
- color_type: color::ColorType,
- ) -> ImageResult<()> {
- self.encode(buf, width, height, color_type)
- }
-}
-
-fn get_unsupported_error_message(c: color::ColorType) -> String {
- format!(
- "Unsupported color type {:?}. Supported types: RGB(8), RGBA(8), Gray(8), GrayA(8).",
- c
- )
-}
-
-/// Returns a tuple representing: (dib header size, written pixel size, palette color count).
-fn get_pixel_info(c: color::ColorType, palette: Option<&[[u8; 3]]>) -> io::Result<(u32, u32, u32)> {
- let sizes = match c {
- color::ColorType::Rgb8 => (BITMAPINFOHEADER_SIZE, 3, 0),
- color::ColorType::Rgba8 => (BITMAPV4HEADER_SIZE, 4, 0),
- color::ColorType::L8 => (
- BITMAPINFOHEADER_SIZE,
- 1,
- palette.map(|p| p.len()).unwrap_or(256) as u32,
- ),
- color::ColorType::La8 => (
- BITMAPINFOHEADER_SIZE,
- 1,
- palette.map(|p| p.len()).unwrap_or(256) as u32,
- ),
- _ => {
- return Err(io::Error::new(
- io::ErrorKind::InvalidInput,
- &get_unsupported_error_message(c)[..],
- ))
- }
- };
-
- Ok(sizes)
-}
-
-#[cfg(test)]
-mod tests {
- use super::super::BmpDecoder;
- use super::BmpEncoder;
- use crate::color::ColorType;
- use crate::image::ImageDecoder;
- use std::io::Cursor;
-
- fn round_trip_image(image: &[u8], width: u32, height: u32, c: ColorType) -> Vec<u8> {
- let mut encoded_data = Vec::new();
- {
- let mut encoder = BmpEncoder::new(&mut encoded_data);
- encoder
- .encode(&image, width, height, c)
- .expect("could not encode image");
- }
-
- let decoder = BmpDecoder::new(Cursor::new(&encoded_data)).expect("failed to decode");
-
- let mut buf = vec![0; decoder.total_bytes() as usize];
- decoder.read_image(&mut buf).expect("failed to decode");
- buf
- }
-
- #[test]
- fn round_trip_single_pixel_rgb() {
- let image = [255u8, 0, 0]; // single red pixel
- let decoded = round_trip_image(&image, 1, 1, ColorType::Rgb8);
- assert_eq!(3, decoded.len());
- assert_eq!(255, decoded[0]);
- assert_eq!(0, decoded[1]);
- assert_eq!(0, decoded[2]);
- }
-
- #[test]
- #[cfg(target_pointer_width = "64")]
- fn huge_files_return_error() {
- let mut encoded_data = Vec::new();
- let image = vec![0u8; 3 * 40_000 * 40_000]; // 40_000x40_000 pixels, 3 bytes per pixel, allocated on the heap
- let mut encoder = BmpEncoder::new(&mut encoded_data);
- let result = encoder.encode(&image, 40_000, 40_000, ColorType::Rgb8);
- assert!(result.is_err());
- }
-
- #[test]
- fn round_trip_single_pixel_rgba() {
- let image = [1, 2, 3, 4];
- let decoded = round_trip_image(&image, 1, 1, ColorType::Rgba8);
- assert_eq!(&decoded[..], &image[..]);
- }
-
- #[test]
- fn round_trip_3px_rgb() {
- let image = [0u8; 3 * 3 * 3]; // 3x3 pixels, 3 bytes per pixel
- let _decoded = round_trip_image(&image, 3, 3, ColorType::Rgb8);
- }
-
- #[test]
- fn round_trip_gray() {
- let image = [0u8, 1, 2]; // 3 pixels
- let decoded = round_trip_image(&image, 3, 1, ColorType::L8);
- // should be read back as 3 RGB pixels
- assert_eq!(9, decoded.len());
- assert_eq!(0, decoded[0]);
- assert_eq!(0, decoded[1]);
- assert_eq!(0, decoded[2]);
- assert_eq!(1, decoded[3]);
- assert_eq!(1, decoded[4]);
- assert_eq!(1, decoded[5]);
- assert_eq!(2, decoded[6]);
- assert_eq!(2, decoded[7]);
- assert_eq!(2, decoded[8]);
- }
-
- #[test]
- fn round_trip_graya() {
- let image = [0u8, 0, 1, 0, 2, 0]; // 3 pixels, each with an alpha channel
- let decoded = round_trip_image(&image, 1, 3, ColorType::La8);
- // should be read back as 3 RGB pixels
- assert_eq!(9, decoded.len());
- assert_eq!(0, decoded[0]);
- assert_eq!(0, decoded[1]);
- assert_eq!(0, decoded[2]);
- assert_eq!(1, decoded[3]);
- assert_eq!(1, decoded[4]);
- assert_eq!(1, decoded[5]);
- assert_eq!(2, decoded[6]);
- assert_eq!(2, decoded[7]);
- assert_eq!(2, decoded[8]);
- }
-}
diff --git a/vendor/image/src/codecs/bmp/mod.rs b/vendor/image/src/codecs/bmp/mod.rs
deleted file mode 100644
index 549b1cf..0000000
--- a/vendor/image/src/codecs/bmp/mod.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//! Decoding and Encoding of BMP Images
-//!
-//! A decoder and encoder for BMP (Windows Bitmap) images
-//!
-//! # Related Links
-//! * <https://msdn.microsoft.com/en-us/library/windows/desktop/dd183375%28v=vs.85%29.aspx>
-//! * <https://en.wikipedia.org/wiki/BMP_file_format>
-//!
-
-pub use self::decoder::BmpDecoder;
-pub use self::encoder::BmpEncoder;
-
-mod decoder;
-mod encoder;