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>), } 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 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 { 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( 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>( pixel_iter: &mut ChunksMut, 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>( pixel_iter: &mut ChunksMut, 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>( pixel_iter: &mut ChunksMut, 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>( pixel_iter: &mut ChunksMut, 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 { 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 { 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 { 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>, bitfields: Option, } enum RLEInsn { EndOfFile, EndOfRow, Delta(u8, u8), Absolute(u8, Vec), PixelRun(u8, u8), } impl BmpDecoder { fn new_decoder(reader: R) -> BmpDecoder { 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> { 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> { 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> { 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::()?; self.reader.read_u32::()?; self.data_offset = u64::from(self.reader.read_u32::()?); 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::()?); self.height = i32::from(self.reader.read_u16::()?); 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::()? != 1 { return Err(DecoderError::MoreThanOnePlane.into()); } self.bit_count = self.reader.read_u16::()?; 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::()?; self.height = self.reader.read_i32::()?; // 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::()? != 1 { return Err(DecoderError::MoreThanOnePlane.into()); } self.bit_count = self.reader.read_u16::()?; let image_type_u32 = self.reader.read_u32::()?; // 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::()?; self.reader.read_u32::()?; self.reader.read_u32::()?; self.colors_used = self.reader.read_u32::()?; // 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::()?; Ok(()) } fn read_bitmasks(&mut self) -> ImageResult<()> { let r_mask = self.reader.read_u32::()?; let g_mask = self.reader.read_u32::()?; let b_mask = self.reader.read_u32::()?; let a_mask = match self.bmp_header_type { BMPHeaderType::V3 | BMPHeaderType::V4 | BMPHeaderType::V5 => { self.reader.read_u32::()? } _ => 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::()?; 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 { 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::()?); 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::()?; 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>` pub struct BmpReader(Cursor>, PhantomData); impl Read for BmpReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { self.0.read(buf) } fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { 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 { type Reader = BmpReader; 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 { 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 { fn read_rect_with_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 = 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); } } }