Skip to main content

ai_image/codecs/bmp/
decoder.rs

1use crate::utils::vec_try_with_capacity;
2use alloc::{borrow::ToOwned, boxed::Box, format, vec, vec::Vec};
3use core::cmp::{self, Ordering};
4use core::iter::{repeat, Rev};
5use core::slice::ChunksExactMut;
6use core::{error, fmt};
7use no_std_io::io::{self, BufRead, Seek, SeekFrom};
8
9use byteorder_lite::{LittleEndian, ReadBytesExt};
10
11use crate::color::ColorType;
12use crate::error::{
13    DecodingError, ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind,
14};
15use crate::io::free_functions::load_rect;
16use crate::io::ReadExt;
17use crate::{ImageDecoder, ImageDecoderRect, ImageFormat};
18
19const BITMAPCOREHEADER_SIZE: u32 = 12;
20const BITMAPINFOHEADER_SIZE: u32 = 40;
21const BITMAPV2HEADER_SIZE: u32 = 52;
22const BITMAPV3HEADER_SIZE: u32 = 56;
23const BITMAPV4HEADER_SIZE: u32 = 108;
24const BITMAPV5HEADER_SIZE: u32 = 124;
25
26static LOOKUP_TABLE_3_BIT_TO_8_BIT: [u8; 8] = [0, 36, 73, 109, 146, 182, 219, 255];
27static LOOKUP_TABLE_4_BIT_TO_8_BIT: [u8; 16] = [
28    0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255,
29];
30static LOOKUP_TABLE_5_BIT_TO_8_BIT: [u8; 32] = [
31    0, 8, 16, 25, 33, 41, 49, 58, 66, 74, 82, 90, 99, 107, 115, 123, 132, 140, 148, 156, 165, 173,
32    181, 189, 197, 206, 214, 222, 230, 239, 247, 255,
33];
34static LOOKUP_TABLE_6_BIT_TO_8_BIT: [u8; 64] = [
35    0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 45, 49, 53, 57, 61, 65, 69, 73, 77, 81, 85, 89, 93,
36    97, 101, 105, 109, 113, 117, 121, 125, 130, 134, 138, 142, 146, 150, 154, 158, 162, 166, 170,
37    174, 178, 182, 186, 190, 194, 198, 202, 206, 210, 215, 219, 223, 227, 231, 235, 239, 243, 247,
38    251, 255,
39];
40
41static R5_G5_B5_COLOR_MASK: Bitfields = Bitfields {
42    r: Bitfield { len: 5, shift: 10 },
43    g: Bitfield { len: 5, shift: 5 },
44    b: Bitfield { len: 5, shift: 0 },
45    a: Bitfield { len: 0, shift: 0 },
46};
47const R8_G8_B8_COLOR_MASK: Bitfields = Bitfields {
48    r: Bitfield { len: 8, shift: 24 },
49    g: Bitfield { len: 8, shift: 16 },
50    b: Bitfield { len: 8, shift: 8 },
51    a: Bitfield { len: 0, shift: 0 },
52};
53const R8_G8_B8_A8_COLOR_MASK: Bitfields = Bitfields {
54    r: Bitfield { len: 8, shift: 16 },
55    g: Bitfield { len: 8, shift: 8 },
56    b: Bitfield { len: 8, shift: 0 },
57    a: Bitfield { len: 8, shift: 24 },
58};
59
60const RLE_ESCAPE: u8 = 0;
61const RLE_ESCAPE_EOL: u8 = 0;
62const RLE_ESCAPE_EOF: u8 = 1;
63const RLE_ESCAPE_DELTA: u8 = 2;
64
65/// The maximum width/height the decoder will process.
66const MAX_WIDTH_HEIGHT: i32 = 0xFFFF;
67
68#[derive(PartialEq, Copy, Clone)]
69enum ImageType {
70    Palette,
71    RGB16,
72    RGB24,
73    RGB32,
74    RGBA32,
75    RLE8,
76    RLE4,
77    Bitfields16,
78    Bitfields32,
79}
80
81#[derive(PartialEq)]
82enum BMPHeaderType {
83    Core,
84    Info,
85    V2,
86    V3,
87    V4,
88    V5,
89}
90
91#[derive(PartialEq)]
92enum FormatFullBytes {
93    RGB24,
94    RGB32,
95    RGBA32,
96    Format888,
97}
98
99enum Chunker<'a> {
100    FromTop(ChunksExactMut<'a, u8>),
101    FromBottom(Rev<ChunksExactMut<'a, u8>>),
102}
103
104pub(crate) struct RowIterator<'a> {
105    chunks: Chunker<'a>,
106}
107
108impl<'a> Iterator for RowIterator<'a> {
109    type Item = &'a mut [u8];
110
111    #[inline(always)]
112    fn next(&mut self) -> Option<&'a mut [u8]> {
113        match self.chunks {
114            Chunker::FromTop(ref mut chunks) => chunks.next(),
115            Chunker::FromBottom(ref mut chunks) => chunks.next(),
116        }
117    }
118}
119
120/// All errors that can occur when attempting to parse a BMP
121#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
122enum DecoderError {
123    // Failed to decompress RLE data.
124    CorruptRleData,
125
126    /// The bitfield mask interleaves set and unset bits
127    BitfieldMaskNonContiguous,
128    /// Bitfield mask invalid (e.g. too long for specified type)
129    BitfieldMaskInvalid,
130    /// Bitfield (of the specified width – 16- or 32-bit) mask not present
131    BitfieldMaskMissing(u32),
132    /// Bitfield (of the specified width – 16- or 32-bit) masks not present
133    BitfieldMasksMissing(u32),
134
135    /// BMP's "BM" signature wrong or missing
136    BmpSignatureInvalid,
137    /// More than the exactly one allowed plane specified by the format
138    MoreThanOnePlane,
139    /// Invalid amount of bits per channel for the specified image type
140    InvalidChannelWidth(ChannelWidthError, u16),
141
142    /// The width is negative
143    NegativeWidth(i32),
144    /// One of the dimensions is larger than a soft limit
145    ImageTooLarge(i32, i32),
146    /// The height is `i32::min_value()`
147    ///
148    /// General negative heights specify top-down DIBs
149    InvalidHeight,
150
151    /// Specified image type is invalid for top-down BMPs (i.e. is compressed)
152    ImageTypeInvalidForTopDown(u32),
153    /// Image type not currently recognized by the decoder
154    ImageTypeUnknown(u32),
155
156    /// Bitmap header smaller than the core header
157    HeaderTooSmall(u32),
158
159    /// The palette is bigger than allowed by the bit count of the BMP
160    PaletteSizeExceeded {
161        colors_used: u32,
162        bit_count: u16,
163    },
164}
165
166impl fmt::Display for DecoderError {
167    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168        match self {
169            DecoderError::CorruptRleData => f.write_str("Corrupt RLE data"),
170            DecoderError::BitfieldMaskNonContiguous => f.write_str("Non-contiguous bitfield mask"),
171            DecoderError::BitfieldMaskInvalid => f.write_str("Invalid bitfield mask"),
172            DecoderError::BitfieldMaskMissing(bb) => {
173                f.write_fmt(format_args!("Missing {bb}-bit bitfield mask"))
174            }
175            DecoderError::BitfieldMasksMissing(bb) => {
176                f.write_fmt(format_args!("Missing {bb}-bit bitfield masks"))
177            }
178            DecoderError::BmpSignatureInvalid => f.write_str("BMP signature not found"),
179            DecoderError::MoreThanOnePlane => f.write_str("More than one plane"),
180            DecoderError::InvalidChannelWidth(tp, n) => {
181                f.write_fmt(format_args!("Invalid channel bit count for {tp}: {n}"))
182            }
183            DecoderError::NegativeWidth(w) => f.write_fmt(format_args!("Negative width ({w})")),
184            DecoderError::ImageTooLarge(w, h) => f.write_fmt(format_args!(
185                "Image too large (one of ({w}, {h}) > soft limit of {MAX_WIDTH_HEIGHT})"
186            )),
187            DecoderError::InvalidHeight => f.write_str("Invalid height"),
188            DecoderError::ImageTypeInvalidForTopDown(tp) => f.write_fmt(format_args!(
189                "Invalid image type {tp} for top-down image."
190            )),
191            DecoderError::ImageTypeUnknown(tp) => {
192                f.write_fmt(format_args!("Unknown image compression type {tp}"))
193            }
194            DecoderError::HeaderTooSmall(s) => {
195                f.write_fmt(format_args!("Bitmap header too small ({s} bytes)"))
196            }
197            DecoderError::PaletteSizeExceeded {
198                colors_used,
199                bit_count,
200            } => f.write_fmt(format_args!(
201                "Palette size {colors_used} exceeds maximum size for BMP with bit count of {bit_count}"
202            )),
203        }
204    }
205}
206
207impl From<DecoderError> for ImageError {
208    fn from(e: DecoderError) -> ImageError {
209        ImageError::Decoding(DecodingError::new(ImageFormat::Bmp.into(), e))
210    }
211}
212
213impl error::Error for DecoderError {}
214
215/// Distinct image types whose saved channel width can be invalid
216#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
217enum ChannelWidthError {
218    /// RGB
219    Rgb,
220    /// 8-bit run length encoding
221    Rle8,
222    /// 4-bit run length encoding
223    Rle4,
224    /// Bitfields (16- or 32-bit)
225    Bitfields,
226}
227
228impl fmt::Display for ChannelWidthError {
229    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
230        f.write_str(match self {
231            ChannelWidthError::Rgb => "RGB",
232            ChannelWidthError::Rle8 => "RLE8",
233            ChannelWidthError::Rle4 => "RLE4",
234            ChannelWidthError::Bitfields => "bitfields",
235        })
236    }
237}
238
239/// Convenience function to check if the combination of width, length and number of
240/// channels would result in a buffer that would overflow.
241fn check_for_overflow(width: i32, length: i32, channels: usize) -> ImageResult<()> {
242    num_bytes(width, length, channels)
243        .map(|_| ())
244        .ok_or_else(|| {
245            ImageError::Unsupported(UnsupportedError::from_format_and_kind(
246                ImageFormat::Bmp.into(),
247                UnsupportedErrorKind::GenericFeature(format!(
248                    "Image dimensions ({width}x{length} w/{channels} channels) are too large"
249                )),
250            ))
251        })
252}
253
254/// Calculate how many many bytes a buffer holding a decoded image with these properties would
255/// require. Returns `None` if the buffer size would overflow or if one of the sizes are negative.
256fn num_bytes(width: i32, length: i32, channels: usize) -> Option<usize> {
257    if width <= 0 || length <= 0 {
258        None
259    } else {
260        match channels.checked_mul(width as usize) {
261            Some(n) => n.checked_mul(length as usize),
262            None => None,
263        }
264    }
265}
266
267/// Call the provided function on each row of the provided buffer, returning Err if the provided
268/// function returns an error, extends the buffer if it's not large enough.
269fn with_rows<F>(
270    buffer: &mut [u8],
271    width: i32,
272    height: i32,
273    channels: usize,
274    top_down: bool,
275    mut func: F,
276) -> io::Result<()>
277where
278    F: FnMut(&mut [u8]) -> io::Result<()>,
279{
280    // An overflow should already have been checked for when this is called,
281    // though we check anyhow, as it somehow seems to increase performance slightly.
282    let row_width = channels.checked_mul(width as usize).unwrap();
283    let full_image_size = row_width.checked_mul(height as usize).unwrap();
284    assert_eq!(buffer.len(), full_image_size);
285
286    if !top_down {
287        for row in buffer.chunks_mut(row_width).rev() {
288            func(row)?;
289        }
290    } else {
291        for row in buffer.chunks_mut(row_width) {
292            func(row)?;
293        }
294    }
295    Ok(())
296}
297
298fn set_8bit_pixel_run<'a, T: Iterator<Item = &'a u8>>(
299    pixel_iter: &mut ChunksExactMut<u8>,
300    palette: &[[u8; 3]],
301    indices: T,
302    n_pixels: usize,
303) -> bool {
304    for idx in indices.take(n_pixels) {
305        if let Some(pixel) = pixel_iter.next() {
306            let rgb = palette[*idx as usize];
307            pixel[0] = rgb[0];
308            pixel[1] = rgb[1];
309            pixel[2] = rgb[2];
310        } else {
311            return false;
312        }
313    }
314    true
315}
316
317fn set_4bit_pixel_run<'a, T: Iterator<Item = &'a u8>>(
318    pixel_iter: &mut ChunksExactMut<u8>,
319    palette: &[[u8; 3]],
320    indices: T,
321    mut n_pixels: usize,
322) -> bool {
323    for idx in indices {
324        macro_rules! set_pixel {
325            ($i:expr) => {
326                if n_pixels == 0 {
327                    break;
328                }
329                if let Some(pixel) = pixel_iter.next() {
330                    let rgb = palette[$i as usize];
331                    pixel[0] = rgb[0];
332                    pixel[1] = rgb[1];
333                    pixel[2] = rgb[2];
334                } else {
335                    return false;
336                }
337                n_pixels -= 1;
338            };
339        }
340        set_pixel!(idx >> 4);
341        set_pixel!(idx & 0xf);
342    }
343    true
344}
345
346#[rustfmt::skip]
347fn set_2bit_pixel_run<'a, T: Iterator<Item = &'a u8>>(
348    pixel_iter: &mut ChunksExactMut<u8>,
349    palette: &[[u8; 3]],
350    indices: T,
351    mut n_pixels: usize,
352) -> bool {
353    for idx in indices {
354        macro_rules! set_pixel {
355            ($i:expr) => {
356                if n_pixels == 0 {
357                    break;
358                }
359                if let Some(pixel) = pixel_iter.next() {
360                    let rgb = palette[$i as usize];
361                    pixel[0] = rgb[0];
362                    pixel[1] = rgb[1];
363                    pixel[2] = rgb[2];
364                } else {
365                    return false;
366                }
367                n_pixels -= 1;
368            };
369        }
370        set_pixel!((idx >> 6) & 0x3u8);
371        set_pixel!((idx >> 4) & 0x3u8);
372        set_pixel!((idx >> 2) & 0x3u8);
373        set_pixel!( idx       & 0x3u8);
374    }
375    true
376}
377
378fn set_1bit_pixel_run<'a, T: Iterator<Item = &'a u8>>(
379    pixel_iter: &mut ChunksExactMut<u8>,
380    palette: &[[u8; 3]],
381    indices: T,
382) {
383    for idx in indices {
384        let mut bit = 0x80;
385        loop {
386            if let Some(pixel) = pixel_iter.next() {
387                let rgb = palette[usize::from((idx & bit) != 0)];
388                pixel[0] = rgb[0];
389                pixel[1] = rgb[1];
390                pixel[2] = rgb[2];
391            } else {
392                return;
393            }
394
395            bit >>= 1;
396            if bit == 0 {
397                break;
398            }
399        }
400    }
401}
402
403#[derive(PartialEq, Eq)]
404struct Bitfield {
405    shift: u32,
406    len: u32,
407}
408
409impl Bitfield {
410    fn from_mask(mask: u32, max_len: u32) -> ImageResult<Bitfield> {
411        if mask == 0 {
412            return Ok(Bitfield { shift: 0, len: 0 });
413        }
414        let mut shift = mask.trailing_zeros();
415        let mut len = (!(mask >> shift)).trailing_zeros();
416        if len != mask.count_ones() {
417            return Err(DecoderError::BitfieldMaskNonContiguous.into());
418        }
419        if len + shift > max_len {
420            return Err(DecoderError::BitfieldMaskInvalid.into());
421        }
422        if len > 8 {
423            shift += len - 8;
424            len = 8;
425        }
426        Ok(Bitfield { shift, len })
427    }
428
429    fn read(&self, data: u32) -> u8 {
430        let data = data >> self.shift;
431        match self.len {
432            1 => ((data & 0b1) * 0xff) as u8,
433            2 => ((data & 0b11) * 0x55) as u8,
434            3 => LOOKUP_TABLE_3_BIT_TO_8_BIT[(data & 0b00_0111) as usize],
435            4 => LOOKUP_TABLE_4_BIT_TO_8_BIT[(data & 0b00_1111) as usize],
436            5 => LOOKUP_TABLE_5_BIT_TO_8_BIT[(data & 0b01_1111) as usize],
437            6 => LOOKUP_TABLE_6_BIT_TO_8_BIT[(data & 0b11_1111) as usize],
438            7 => (((data & 0x7f) << 1) | ((data & 0x7f) >> 6)) as u8,
439            8 => (data & 0xff) as u8,
440            _ => panic!(),
441        }
442    }
443}
444
445#[derive(PartialEq, Eq)]
446struct Bitfields {
447    r: Bitfield,
448    g: Bitfield,
449    b: Bitfield,
450    a: Bitfield,
451}
452
453impl Bitfields {
454    fn from_mask(
455        r_mask: u32,
456        g_mask: u32,
457        b_mask: u32,
458        a_mask: u32,
459        max_len: u32,
460    ) -> ImageResult<Bitfields> {
461        let bitfields = Bitfields {
462            r: Bitfield::from_mask(r_mask, max_len)?,
463            g: Bitfield::from_mask(g_mask, max_len)?,
464            b: Bitfield::from_mask(b_mask, max_len)?,
465            a: Bitfield::from_mask(a_mask, max_len)?,
466        };
467        if bitfields.r.len == 0 || bitfields.g.len == 0 || bitfields.b.len == 0 {
468            return Err(DecoderError::BitfieldMaskMissing(max_len).into());
469        }
470        Ok(bitfields)
471    }
472}
473
474/// A bmp decoder
475pub struct BmpDecoder<R> {
476    reader: R,
477
478    bmp_header_type: BMPHeaderType,
479    indexed_color: bool,
480
481    width: i32,
482    height: i32,
483    data_offset: u64,
484    top_down: bool,
485    no_file_header: bool,
486    add_alpha_channel: bool,
487    has_loaded_metadata: bool,
488    image_type: ImageType,
489
490    bit_count: u16,
491    colors_used: u32,
492    palette: Option<Vec<[u8; 3]>>,
493    bitfields: Option<Bitfields>,
494}
495
496enum RLEInsn {
497    EndOfFile,
498    EndOfRow,
499    Delta(u8, u8),
500    Absolute(u8, Vec<u8>),
501    PixelRun(u8, u8),
502}
503
504impl<R: BufRead + Seek> BmpDecoder<R> {
505    fn new_decoder(reader: R) -> BmpDecoder<R> {
506        BmpDecoder {
507            reader,
508
509            bmp_header_type: BMPHeaderType::Info,
510            indexed_color: false,
511
512            width: 0,
513            height: 0,
514            data_offset: 0,
515            top_down: false,
516            no_file_header: false,
517            add_alpha_channel: false,
518            has_loaded_metadata: false,
519            image_type: ImageType::Palette,
520
521            bit_count: 0,
522            colors_used: 0,
523            palette: None,
524            bitfields: None,
525        }
526    }
527
528    /// Create a new decoder that decodes from the stream ```r```
529    pub fn new(reader: R) -> ImageResult<BmpDecoder<R>> {
530        let mut decoder = Self::new_decoder(reader);
531        decoder.read_metadata()?;
532        Ok(decoder)
533    }
534
535    /// Create a new decoder that decodes from the stream ```r``` without first
536    /// reading a BITMAPFILEHEADER. This is useful for decoding the `CF_DIB` format
537    /// directly from the Windows clipboard.
538    pub fn new_without_file_header(reader: R) -> ImageResult<BmpDecoder<R>> {
539        let mut decoder = Self::new_decoder(reader);
540        decoder.no_file_header = true;
541        decoder.read_metadata()?;
542        Ok(decoder)
543    }
544
545    #[cfg(feature = "ico")]
546    pub(crate) fn new_with_ico_format(reader: R) -> ImageResult<BmpDecoder<R>> {
547        let mut decoder = Self::new_decoder(reader);
548        decoder.read_metadata_in_ico_format()?;
549        Ok(decoder)
550    }
551
552    /// If true, the palette in BMP does not apply to the image even if it is found.
553    /// In other words, the output image is the indexed color.
554    pub fn set_indexed_color(&mut self, indexed_color: bool) {
555        self.indexed_color = indexed_color;
556    }
557
558    #[cfg(feature = "ico")]
559    pub(crate) fn reader(&mut self) -> &mut R {
560        &mut self.reader
561    }
562
563    fn read_file_header(&mut self) -> ImageResult<()> {
564        if self.no_file_header {
565            return Ok(());
566        }
567        let mut signature = [0; 2];
568        self.reader.read_exact(&mut signature)?;
569
570        if signature != b"BM"[..] {
571            return Err(DecoderError::BmpSignatureInvalid.into());
572        }
573
574        // The next 8 bytes represent file size, followed the 4 reserved bytes
575        // We're not interesting these values
576        self.reader.read_u32::<LittleEndian>()?;
577        self.reader.read_u32::<LittleEndian>()?;
578
579        self.data_offset = u64::from(self.reader.read_u32::<LittleEndian>()?);
580
581        Ok(())
582    }
583
584    /// Read BITMAPCOREHEADER <https://msdn.microsoft.com/en-us/library/vs/alm/dd183372(v=vs.85).aspx>
585    ///
586    /// returns Err if any of the values are invalid.
587    fn read_bitmap_core_header(&mut self) -> ImageResult<()> {
588        // As height/width values in BMP files with core headers are only 16 bits long,
589        // they won't be larger than `MAX_WIDTH_HEIGHT`.
590        self.width = i32::from(self.reader.read_u16::<LittleEndian>()?);
591        self.height = i32::from(self.reader.read_u16::<LittleEndian>()?);
592
593        check_for_overflow(self.width, self.height, self.num_channels())?;
594
595        // Number of planes (format specifies that this should be 1).
596        if self.reader.read_u16::<LittleEndian>()? != 1 {
597            return Err(DecoderError::MoreThanOnePlane.into());
598        }
599
600        self.bit_count = self.reader.read_u16::<LittleEndian>()?;
601        self.image_type = match self.bit_count {
602            1 | 4 | 8 => ImageType::Palette,
603            24 => ImageType::RGB24,
604            _ => {
605                return Err(DecoderError::InvalidChannelWidth(
606                    ChannelWidthError::Rgb,
607                    self.bit_count,
608                )
609                .into())
610            }
611        };
612
613        Ok(())
614    }
615
616    /// Read BITMAPINFOHEADER <https://msdn.microsoft.com/en-us/library/vs/alm/dd183376(v=vs.85).aspx>
617    /// or BITMAPV{2|3|4|5}HEADER.
618    ///
619    /// returns Err if any of the values are invalid.
620    fn read_bitmap_info_header(&mut self) -> ImageResult<()> {
621        self.width = self.reader.read_i32::<LittleEndian>()?;
622        self.height = self.reader.read_i32::<LittleEndian>()?;
623
624        // Width can not be negative
625        if self.width < 0 {
626            return Err(DecoderError::NegativeWidth(self.width).into());
627        } else if self.width > MAX_WIDTH_HEIGHT || self.height > MAX_WIDTH_HEIGHT {
628            // Limit very large image sizes to avoid OOM issues. Images with these sizes are
629            // unlikely to be valid anyhow.
630            return Err(DecoderError::ImageTooLarge(self.width, self.height).into());
631        }
632
633        if self.height == i32::MIN {
634            return Err(DecoderError::InvalidHeight.into());
635        }
636
637        // A negative height indicates a top-down DIB.
638        if self.height < 0 {
639            self.height *= -1;
640            self.top_down = true;
641        }
642
643        check_for_overflow(self.width, self.height, self.num_channels())?;
644
645        // Number of planes (format specifies that this should be 1).
646        if self.reader.read_u16::<LittleEndian>()? != 1 {
647            return Err(DecoderError::MoreThanOnePlane.into());
648        }
649
650        self.bit_count = self.reader.read_u16::<LittleEndian>()?;
651        let image_type_u32 = self.reader.read_u32::<LittleEndian>()?;
652
653        // Top-down dibs can not be compressed.
654        if self.top_down && image_type_u32 != 0 && image_type_u32 != 3 {
655            return Err(DecoderError::ImageTypeInvalidForTopDown(image_type_u32).into());
656        }
657        self.image_type = match image_type_u32 {
658            0 => match self.bit_count {
659                1 | 2 | 4 | 8 => ImageType::Palette,
660                16 => ImageType::RGB16,
661                24 => ImageType::RGB24,
662                32 if self.add_alpha_channel => ImageType::RGBA32,
663                32 => ImageType::RGB32,
664                _ => {
665                    return Err(DecoderError::InvalidChannelWidth(
666                        ChannelWidthError::Rgb,
667                        self.bit_count,
668                    )
669                    .into())
670                }
671            },
672            1 => match self.bit_count {
673                8 => ImageType::RLE8,
674                _ => {
675                    return Err(DecoderError::InvalidChannelWidth(
676                        ChannelWidthError::Rle8,
677                        self.bit_count,
678                    )
679                    .into())
680                }
681            },
682            2 => match self.bit_count {
683                4 => ImageType::RLE4,
684                _ => {
685                    return Err(DecoderError::InvalidChannelWidth(
686                        ChannelWidthError::Rle4,
687                        self.bit_count,
688                    )
689                    .into())
690                }
691            },
692            3 => match self.bit_count {
693                16 => ImageType::Bitfields16,
694                32 => ImageType::Bitfields32,
695                _ => {
696                    return Err(DecoderError::InvalidChannelWidth(
697                        ChannelWidthError::Bitfields,
698                        self.bit_count,
699                    )
700                    .into())
701                }
702            },
703            4 => {
704                // JPEG compression is not implemented yet.
705                return Err(ImageError::Unsupported(
706                    UnsupportedError::from_format_and_kind(
707                        ImageFormat::Bmp.into(),
708                        UnsupportedErrorKind::GenericFeature("JPEG compression".to_owned()),
709                    ),
710                ));
711            }
712            5 => {
713                // PNG compression is not implemented yet.
714                return Err(ImageError::Unsupported(
715                    UnsupportedError::from_format_and_kind(
716                        ImageFormat::Bmp.into(),
717                        UnsupportedErrorKind::GenericFeature("PNG compression".to_owned()),
718                    ),
719                ));
720            }
721            11..=13 => {
722                // CMYK types are not implemented yet.
723                return Err(ImageError::Unsupported(
724                    UnsupportedError::from_format_and_kind(
725                        ImageFormat::Bmp.into(),
726                        UnsupportedErrorKind::GenericFeature("CMYK format".to_owned()),
727                    ),
728                ));
729            }
730            _ => {
731                // Unknown compression type.
732                return Err(DecoderError::ImageTypeUnknown(image_type_u32).into());
733            }
734        };
735
736        // The next 12 bytes represent data array size in bytes,
737        // followed the horizontal and vertical printing resolutions
738        // We will calculate the pixel array size using width & height of image
739        // We're not interesting the horz or vert printing resolutions
740        self.reader.read_u32::<LittleEndian>()?;
741        self.reader.read_u32::<LittleEndian>()?;
742        self.reader.read_u32::<LittleEndian>()?;
743
744        self.colors_used = self.reader.read_u32::<LittleEndian>()?;
745
746        // The next 4 bytes represent number of "important" colors
747        // We're not interested in this value, so we'll skip it
748        self.reader.read_u32::<LittleEndian>()?;
749
750        Ok(())
751    }
752
753    fn read_bitmasks(&mut self) -> ImageResult<()> {
754        let r_mask = self.reader.read_u32::<LittleEndian>()?;
755        let g_mask = self.reader.read_u32::<LittleEndian>()?;
756        let b_mask = self.reader.read_u32::<LittleEndian>()?;
757
758        let a_mask = match self.bmp_header_type {
759            BMPHeaderType::V3 | BMPHeaderType::V4 | BMPHeaderType::V5 => {
760                self.reader.read_u32::<LittleEndian>()?
761            }
762            _ => 0,
763        };
764
765        self.bitfields = match self.image_type {
766            ImageType::Bitfields16 => {
767                Some(Bitfields::from_mask(r_mask, g_mask, b_mask, a_mask, 16)?)
768            }
769            ImageType::Bitfields32 => {
770                Some(Bitfields::from_mask(r_mask, g_mask, b_mask, a_mask, 32)?)
771            }
772            _ => None,
773        };
774
775        if self.bitfields.is_some() && a_mask != 0 {
776            self.add_alpha_channel = true;
777        }
778
779        Ok(())
780    }
781
782    fn read_metadata(&mut self) -> ImageResult<()> {
783        if !self.has_loaded_metadata {
784            self.read_file_header()?;
785            // no_std_io::Seek doesn't provide stream_position()
786            #[allow(clippy::seek_from_current)]
787            let bmp_header_offset = self.reader.seek(SeekFrom::Current(0))?;
788            let bmp_header_size = self.reader.read_u32::<LittleEndian>()?;
789            let bmp_header_end = bmp_header_offset + u64::from(bmp_header_size);
790
791            self.bmp_header_type = match bmp_header_size {
792                BITMAPCOREHEADER_SIZE => BMPHeaderType::Core,
793                BITMAPINFOHEADER_SIZE => BMPHeaderType::Info,
794                BITMAPV2HEADER_SIZE => BMPHeaderType::V2,
795                BITMAPV3HEADER_SIZE => BMPHeaderType::V3,
796                BITMAPV4HEADER_SIZE => BMPHeaderType::V4,
797                BITMAPV5HEADER_SIZE => BMPHeaderType::V5,
798                _ if bmp_header_size < BITMAPCOREHEADER_SIZE => {
799                    // Size of any valid header types won't be smaller than core header type.
800                    return Err(DecoderError::HeaderTooSmall(bmp_header_size).into());
801                }
802                _ => {
803                    return Err(ImageError::Unsupported(
804                        UnsupportedError::from_format_and_kind(
805                            ImageFormat::Bmp.into(),
806                            UnsupportedErrorKind::GenericFeature(format!(
807                                "Unknown bitmap header type (size={bmp_header_size})"
808                            )),
809                        ),
810                    ))
811                }
812            };
813
814            match self.bmp_header_type {
815                BMPHeaderType::Core => {
816                    self.read_bitmap_core_header()?;
817                }
818                BMPHeaderType::Info
819                | BMPHeaderType::V2
820                | BMPHeaderType::V3
821                | BMPHeaderType::V4
822                | BMPHeaderType::V5 => {
823                    self.read_bitmap_info_header()?;
824                }
825            }
826
827            let mut bitmask_bytes_offset = 0;
828            if self.image_type == ImageType::Bitfields16
829                || self.image_type == ImageType::Bitfields32
830            {
831                self.read_bitmasks()?;
832
833                // Per https://learn.microsoft.com/en-us/windows/win32/gdi/bitmap-header-types, bitmaps
834                // using the `BITMAPINFOHEADER`, `BITMAPV4HEADER`, or `BITMAPV5HEADER` structures with
835                // an image type of `BI_BITFIELD` contain RGB bitfield masks immediately after the header.
836                //
837                // `read_bitmasks` correctly reads these from earlier in the header itself but we must
838                // ensure the reader starts on the image data itself, not these extra mask bytes.
839                if matches!(
840                    self.bmp_header_type,
841                    BMPHeaderType::Info | BMPHeaderType::V4 | BMPHeaderType::V5
842                ) {
843                    // This is `size_of::<u32>() * 3` (a red, green, and blue mask), but with less noise.
844                    bitmask_bytes_offset = 12;
845                }
846            };
847
848            self.reader
849                .seek(SeekFrom::Start(bmp_header_end + bitmask_bytes_offset))?;
850
851            match self.image_type {
852                ImageType::Palette | ImageType::RLE4 | ImageType::RLE8 => self.read_palette()?,
853                _ => {}
854            }
855
856            if self.no_file_header {
857                // Use the offset of the end of metadata instead of reading a BMP file header.
858                // no_std_io::Seek doesn't provide stream_position()
859                #[allow(clippy::seek_from_current)]
860                {
861                    self.data_offset = self.reader.seek(SeekFrom::Current(0))?;
862                }
863            }
864
865            self.has_loaded_metadata = true;
866        }
867        Ok(())
868    }
869
870    #[cfg(feature = "ico")]
871    #[doc(hidden)]
872    pub fn read_metadata_in_ico_format(&mut self) -> ImageResult<()> {
873        self.no_file_header = true;
874        self.add_alpha_channel = true;
875        self.read_metadata()?;
876
877        // The height field in an ICO file is doubled to account for the AND mask
878        // (whether or not an AND mask is actually present).
879        self.height /= 2;
880        Ok(())
881    }
882
883    fn get_palette_size(&mut self) -> ImageResult<usize> {
884        match self.colors_used {
885            0 => Ok(1 << self.bit_count),
886            _ => {
887                if self.colors_used > 1 << self.bit_count {
888                    return Err(DecoderError::PaletteSizeExceeded {
889                        colors_used: self.colors_used,
890                        bit_count: self.bit_count,
891                    }
892                    .into());
893                }
894                Ok(self.colors_used as usize)
895            }
896        }
897    }
898
899    fn bytes_per_color(&self) -> usize {
900        match self.bmp_header_type {
901            BMPHeaderType::Core => 3,
902            _ => 4,
903        }
904    }
905
906    fn read_palette(&mut self) -> ImageResult<()> {
907        const MAX_PALETTE_SIZE: usize = 256; // Palette indices are u8.
908
909        let bytes_per_color = self.bytes_per_color();
910        let palette_size = self.get_palette_size()?;
911        let max_length = MAX_PALETTE_SIZE * bytes_per_color;
912
913        let length = palette_size * bytes_per_color;
914        let mut buf = vec_try_with_capacity(max_length)?;
915
916        // Resize and read the palette entries to the buffer.
917        // We limit the buffer to at most 256 colours to avoid any oom issues as
918        // 8-bit images can't reference more than 256 indexes anyhow.
919        buf.resize(cmp::min(length, max_length), 0);
920        self.reader.by_ref().read_exact(&mut buf)?;
921
922        // Allocate 256 entries even if palette_size is smaller, to prevent corrupt files from
923        // causing an out-of-bounds array access.
924        match length.cmp(&max_length) {
925            Ordering::Greater => {
926                self.reader
927                    .seek(SeekFrom::Current((length - max_length) as i64))?;
928            }
929            Ordering::Less => buf.resize(max_length, 0),
930            Ordering::Equal => (),
931        }
932
933        let p: Vec<[u8; 3]> = (0..MAX_PALETTE_SIZE)
934            .map(|i| {
935                let b = buf[bytes_per_color * i];
936                let g = buf[bytes_per_color * i + 1];
937                let r = buf[bytes_per_color * i + 2];
938                [r, g, b]
939            })
940            .collect();
941
942        self.palette = Some(p);
943
944        Ok(())
945    }
946
947    /// Get the palette that is embedded in the BMP image, if any.
948    pub fn get_palette(&self) -> Option<&[[u8; 3]]> {
949        self.palette.as_ref().map(|vec| &vec[..])
950    }
951
952    fn num_channels(&self) -> usize {
953        if self.indexed_color {
954            1
955        } else if self.add_alpha_channel {
956            4
957        } else {
958            3
959        }
960    }
961
962    fn rows<'a>(&self, pixel_data: &'a mut [u8]) -> RowIterator<'a> {
963        let stride = self.width as usize * self.num_channels();
964        if self.top_down {
965            RowIterator {
966                chunks: Chunker::FromTop(pixel_data.chunks_exact_mut(stride)),
967            }
968        } else {
969            RowIterator {
970                chunks: Chunker::FromBottom(pixel_data.chunks_exact_mut(stride).rev()),
971            }
972        }
973    }
974
975    fn read_palettized_pixel_data(&mut self, buf: &mut [u8]) -> ImageResult<()> {
976        let num_channels = self.num_channels();
977        let row_byte_length = ((i32::from(self.bit_count) * self.width + 31) / 32 * 4) as usize;
978        let mut indices = vec![0; row_byte_length];
979        let palette = self.palette.as_ref().unwrap();
980        let bit_count = self.bit_count;
981        let reader = &mut self.reader;
982        let width = self.width as usize;
983        let skip_palette = self.indexed_color;
984
985        reader.seek(SeekFrom::Start(self.data_offset))?;
986
987        if num_channels == 4 {
988            buf.chunks_exact_mut(4).for_each(|c| c[3] = 0xFF);
989        }
990
991        with_rows(
992            buf,
993            self.width,
994            self.height,
995            num_channels,
996            self.top_down,
997            |row| {
998                reader.read_exact(&mut indices)?;
999                if skip_palette {
1000                    row.clone_from_slice(&indices[0..width]);
1001                } else {
1002                    let mut pixel_iter = row.chunks_exact_mut(num_channels);
1003                    match bit_count {
1004                        1 => {
1005                            set_1bit_pixel_run(&mut pixel_iter, palette, indices.iter());
1006                        }
1007                        2 => {
1008                            set_2bit_pixel_run(&mut pixel_iter, palette, indices.iter(), width);
1009                        }
1010                        4 => {
1011                            set_4bit_pixel_run(&mut pixel_iter, palette, indices.iter(), width);
1012                        }
1013                        8 => {
1014                            set_8bit_pixel_run(&mut pixel_iter, palette, indices.iter(), width);
1015                        }
1016                        _ => panic!(),
1017                    }
1018                }
1019                Ok(())
1020            },
1021        )?;
1022
1023        Ok(())
1024    }
1025
1026    fn read_16_bit_pixel_data(
1027        &mut self,
1028        buf: &mut [u8],
1029        bitfields: Option<&Bitfields>,
1030    ) -> ImageResult<()> {
1031        let num_channels = self.num_channels();
1032        let row_padding_len = self.width as usize % 2 * 2;
1033        let row_padding = &mut [0; 2][..row_padding_len];
1034        let bitfields = match bitfields {
1035            Some(b) => b,
1036            None => self.bitfields.as_ref().unwrap(),
1037        };
1038        let reader = &mut self.reader;
1039
1040        reader.seek(SeekFrom::Start(self.data_offset))?;
1041
1042        with_rows(
1043            buf,
1044            self.width,
1045            self.height,
1046            num_channels,
1047            self.top_down,
1048            |row| {
1049                for pixel in row.chunks_mut(num_channels) {
1050                    let data = u32::from(reader.read_u16::<LittleEndian>()?);
1051
1052                    pixel[0] = bitfields.r.read(data);
1053                    pixel[1] = bitfields.g.read(data);
1054                    pixel[2] = bitfields.b.read(data);
1055                    if num_channels == 4 {
1056                        if bitfields.a.len != 0 {
1057                            pixel[3] = bitfields.a.read(data);
1058                        } else {
1059                            pixel[3] = 0xFF;
1060                        }
1061                    }
1062                }
1063                reader.read_exact(row_padding)
1064            },
1065        )?;
1066
1067        Ok(())
1068    }
1069
1070    /// Read image data from a reader in 32-bit formats that use bitfields.
1071    fn read_32_bit_pixel_data(&mut self, buf: &mut [u8]) -> ImageResult<()> {
1072        let num_channels = self.num_channels();
1073
1074        let bitfields = self.bitfields.as_ref().unwrap();
1075
1076        let reader = &mut self.reader;
1077        reader.seek(SeekFrom::Start(self.data_offset))?;
1078
1079        with_rows(
1080            buf,
1081            self.width,
1082            self.height,
1083            num_channels,
1084            self.top_down,
1085            |row| {
1086                for pixel in row.chunks_mut(num_channels) {
1087                    let data = reader.read_u32::<LittleEndian>()?;
1088
1089                    pixel[0] = bitfields.r.read(data);
1090                    pixel[1] = bitfields.g.read(data);
1091                    pixel[2] = bitfields.b.read(data);
1092                    if num_channels == 4 {
1093                        if bitfields.a.len != 0 {
1094                            pixel[3] = bitfields.a.read(data);
1095                        } else {
1096                            pixel[3] = 0xff;
1097                        }
1098                    }
1099                }
1100                Ok(())
1101            },
1102        )?;
1103
1104        Ok(())
1105    }
1106
1107    /// Read image data from a reader where the colours are stored as 8-bit values (24 or 32-bit).
1108    fn read_full_byte_pixel_data(
1109        &mut self,
1110        buf: &mut [u8],
1111        format: &FormatFullBytes,
1112    ) -> ImageResult<()> {
1113        let num_channels = self.num_channels();
1114        let row_padding_len = match *format {
1115            FormatFullBytes::RGB24 => (4 - (self.width as usize * 3) % 4) % 4,
1116            _ => 0,
1117        };
1118        let row_padding = &mut [0; 4][..row_padding_len];
1119
1120        self.reader.seek(SeekFrom::Start(self.data_offset))?;
1121
1122        let reader = &mut self.reader;
1123
1124        with_rows(
1125            buf,
1126            self.width,
1127            self.height,
1128            num_channels,
1129            self.top_down,
1130            |row| {
1131                for pixel in row.chunks_mut(num_channels) {
1132                    if *format == FormatFullBytes::Format888 {
1133                        reader.read_u8()?;
1134                    }
1135
1136                    // Read the colour values (b, g, r).
1137                    // Reading 3 bytes and reversing them is significantly faster than reading one
1138                    // at a time.
1139                    reader.read_exact(&mut pixel[0..3])?;
1140                    pixel[0..3].reverse();
1141
1142                    if *format == FormatFullBytes::RGB32 {
1143                        reader.read_u8()?;
1144                    }
1145
1146                    // Read the alpha channel if present
1147                    if *format == FormatFullBytes::RGBA32 {
1148                        reader.read_exact(&mut pixel[3..4])?;
1149                    } else if num_channels == 4 {
1150                        pixel[3] = 0xFF;
1151                    }
1152                }
1153                reader.read_exact(row_padding)
1154            },
1155        )?;
1156
1157        Ok(())
1158    }
1159
1160    fn read_rle_data(&mut self, buf: &mut [u8], image_type: ImageType) -> ImageResult<()> {
1161        // Seek to the start of the actual image data.
1162        self.reader.seek(SeekFrom::Start(self.data_offset))?;
1163
1164        let num_channels = self.num_channels();
1165        let p = self.palette.as_ref().unwrap();
1166
1167        // Handling deltas in the RLE scheme means that we need to manually
1168        // iterate through rows and pixels.  Even if we didn't have to handle
1169        // deltas, we have to ensure that a single runlength doesn't straddle
1170        // two rows.
1171        let mut row_iter = self.rows(buf);
1172
1173        while let Some(row) = row_iter.next() {
1174            let mut pixel_iter = row.chunks_exact_mut(num_channels);
1175
1176            let mut x = 0;
1177            loop {
1178                let instruction = {
1179                    let control_byte = self.reader.read_u8()?;
1180                    match control_byte {
1181                        RLE_ESCAPE => {
1182                            let op = self.reader.read_u8()?;
1183
1184                            match op {
1185                                RLE_ESCAPE_EOL => RLEInsn::EndOfRow,
1186                                RLE_ESCAPE_EOF => RLEInsn::EndOfFile,
1187                                RLE_ESCAPE_DELTA => {
1188                                    let xdelta = self.reader.read_u8()?;
1189                                    let ydelta = self.reader.read_u8()?;
1190                                    RLEInsn::Delta(xdelta, ydelta)
1191                                }
1192                                _ => {
1193                                    let mut length = op as usize;
1194                                    if self.image_type == ImageType::RLE4 {
1195                                        length = length.div_ceil(2);
1196                                    }
1197                                    length += length & 1;
1198                                    let mut buffer = Vec::new();
1199                                    self.reader.read_exact_vec(&mut buffer, length)?;
1200                                    RLEInsn::Absolute(op, buffer)
1201                                }
1202                            }
1203                        }
1204                        _ => {
1205                            let palette_index = self.reader.read_u8()?;
1206                            RLEInsn::PixelRun(control_byte, palette_index)
1207                        }
1208                    }
1209                };
1210
1211                match instruction {
1212                    RLEInsn::EndOfFile => {
1213                        pixel_iter.for_each(|p| p.fill(0));
1214                        row_iter.for_each(|r| r.fill(0));
1215                        return Ok(());
1216                    }
1217                    RLEInsn::EndOfRow => {
1218                        pixel_iter.for_each(|p| p.fill(0));
1219                        break;
1220                    }
1221                    RLEInsn::Delta(x_delta, y_delta) => {
1222                        // The msdn site on bitmap compression doesn't specify
1223                        // what happens to the values skipped when encountering
1224                        // a delta code, however IE and the windows image
1225                        // preview seems to replace them with black pixels,
1226                        // so we stick to that.
1227
1228                        if y_delta > 0 {
1229                            // Zero out the remainder of the current row.
1230                            pixel_iter.for_each(|p| p.fill(0));
1231
1232                            // If any full rows are skipped, zero them out.
1233                            for _ in 1..y_delta {
1234                                let row = row_iter.next().ok_or(DecoderError::CorruptRleData)?;
1235                                row.fill(0);
1236                            }
1237
1238                            // Set the pixel iterator to the start of the next row.
1239                            pixel_iter = row_iter
1240                                .next()
1241                                .ok_or(DecoderError::CorruptRleData)?
1242                                .chunks_exact_mut(num_channels);
1243
1244                            // Zero out the pixels up to the current point in the row.
1245                            for _ in 0..x {
1246                                pixel_iter
1247                                    .next()
1248                                    .ok_or(DecoderError::CorruptRleData)?
1249                                    .fill(0);
1250                            }
1251                        }
1252
1253                        for _ in 0..x_delta {
1254                            let pixel = pixel_iter.next().ok_or(DecoderError::CorruptRleData)?;
1255                            pixel.fill(0);
1256                        }
1257                        x += x_delta as usize;
1258                    }
1259                    RLEInsn::Absolute(length, indices) => {
1260                        // Absolute mode cannot span rows, so if we run
1261                        // out of pixels to process, we should stop
1262                        // processing the image.
1263                        match image_type {
1264                            ImageType::RLE8 => {
1265                                if !set_8bit_pixel_run(
1266                                    &mut pixel_iter,
1267                                    p,
1268                                    indices.iter(),
1269                                    length as usize,
1270                                ) {
1271                                    return Err(DecoderError::CorruptRleData.into());
1272                                }
1273                            }
1274                            ImageType::RLE4 => {
1275                                if !set_4bit_pixel_run(
1276                                    &mut pixel_iter,
1277                                    p,
1278                                    indices.iter(),
1279                                    length as usize,
1280                                ) {
1281                                    return Err(DecoderError::CorruptRleData.into());
1282                                }
1283                            }
1284                            _ => unreachable!(),
1285                        }
1286                        x += length as usize;
1287                    }
1288                    RLEInsn::PixelRun(n_pixels, palette_index) => {
1289                        match image_type {
1290                            ImageType::RLE8 => {
1291                                // A pixel run isn't allowed to span rows.
1292                                // imagemagick produces invalid images where n_pixels exceeds row length,
1293                                // so we clamp n_pixels to the row length to display them properly:
1294                                // https://github.com/image-rs/image/issues/2321
1295                                //
1296                                // This is like set_8bit_pixel_run() but doesn't fail when `n_pixels` is too large
1297                                let repeat_pixel: [u8; 3] = p[palette_index as usize];
1298                                (&mut pixel_iter).take(n_pixels as usize).for_each(|p| {
1299                                    p[2] = repeat_pixel[2];
1300                                    p[1] = repeat_pixel[1];
1301                                    p[0] = repeat_pixel[0];
1302                                });
1303                            }
1304                            ImageType::RLE4 => {
1305                                if !set_4bit_pixel_run(
1306                                    &mut pixel_iter,
1307                                    p,
1308                                    repeat(&palette_index),
1309                                    n_pixels as usize,
1310                                ) {
1311                                    return Err(DecoderError::CorruptRleData.into());
1312                                }
1313                            }
1314                            _ => unreachable!(),
1315                        }
1316                        x += n_pixels as usize;
1317                    }
1318                }
1319            }
1320        }
1321
1322        Ok(())
1323    }
1324
1325    /// Read the actual data of the image. This function is deliberately not public because it
1326    /// cannot be called multiple times without seeking back the underlying reader in between.
1327    pub(crate) fn read_image_data(&mut self, buf: &mut [u8]) -> ImageResult<()> {
1328        match self.image_type {
1329            ImageType::Palette => self.read_palettized_pixel_data(buf),
1330            ImageType::RGB16 => self.read_16_bit_pixel_data(buf, Some(&R5_G5_B5_COLOR_MASK)),
1331            ImageType::RGB24 => self.read_full_byte_pixel_data(buf, &FormatFullBytes::RGB24),
1332            ImageType::RGB32 => self.read_full_byte_pixel_data(buf, &FormatFullBytes::RGB32),
1333            ImageType::RGBA32 => self.read_full_byte_pixel_data(buf, &FormatFullBytes::RGBA32),
1334            ImageType::RLE8 => self.read_rle_data(buf, ImageType::RLE8),
1335            ImageType::RLE4 => self.read_rle_data(buf, ImageType::RLE4),
1336            ImageType::Bitfields16 => match self.bitfields {
1337                Some(_) => self.read_16_bit_pixel_data(buf, None),
1338                None => Err(DecoderError::BitfieldMasksMissing(16).into()),
1339            },
1340            ImageType::Bitfields32 => match self.bitfields {
1341                Some(R8_G8_B8_COLOR_MASK) => {
1342                    self.read_full_byte_pixel_data(buf, &FormatFullBytes::Format888)
1343                }
1344                Some(R8_G8_B8_A8_COLOR_MASK) => {
1345                    self.read_full_byte_pixel_data(buf, &FormatFullBytes::RGBA32)
1346                }
1347                Some(_) => self.read_32_bit_pixel_data(buf),
1348                None => Err(DecoderError::BitfieldMasksMissing(32).into()),
1349            },
1350        }
1351    }
1352}
1353
1354impl<R: BufRead + Seek> ImageDecoder for BmpDecoder<R> {
1355    fn dimensions(&self) -> (u32, u32) {
1356        (self.width as u32, self.height as u32)
1357    }
1358
1359    fn color_type(&self) -> ColorType {
1360        if self.indexed_color {
1361            ColorType::L8
1362        } else if self.add_alpha_channel {
1363            ColorType::Rgba8
1364        } else {
1365            ColorType::Rgb8
1366        }
1367    }
1368
1369    fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> {
1370        assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes()));
1371        self.read_image_data(buf)
1372    }
1373
1374    fn read_image_boxed(self: Box<Self>, buf: &mut [u8]) -> ImageResult<()> {
1375        (*self).read_image(buf)
1376    }
1377}
1378
1379impl<R: BufRead + Seek> ImageDecoderRect for BmpDecoder<R> {
1380    fn read_rect(
1381        &mut self,
1382        x: u32,
1383        y: u32,
1384        width: u32,
1385        height: u32,
1386        buf: &mut [u8],
1387        row_pitch: usize,
1388    ) -> ImageResult<()> {
1389        // no_std_io::Seek doesn't provide stream_position()
1390        #[allow(clippy::seek_from_current)]
1391        let start = self.reader.seek(SeekFrom::Current(0))?;
1392        load_rect(
1393            x,
1394            y,
1395            width,
1396            height,
1397            buf,
1398            row_pitch,
1399            self,
1400            self.total_bytes() as usize,
1401            |_, _| Ok(()),
1402            |s, buf| s.read_image_data(buf),
1403        )?;
1404        self.reader.seek(SeekFrom::Start(start))?;
1405        Ok(())
1406    }
1407}
1408
1409#[cfg(test)]
1410mod test {
1411    use no_std_io::io::{BufReader, Cursor};
1412
1413    use super::*;
1414
1415    #[test]
1416    fn test_bitfield_len() {
1417        for len in 1..9 {
1418            let bitfield = Bitfield { shift: 0, len };
1419            for i in 0..(1 << len) {
1420                let read = bitfield.read(i);
1421                let calc = (f64::from(i) / f64::from((1 << len) - 1) * 255f64).round() as u8;
1422                if read != calc {
1423                    println!("len:{len} i:{i} read:{read} calc:{calc}");
1424                }
1425                assert_eq!(read, calc);
1426            }
1427        }
1428    }
1429
1430    #[test]
1431    fn read_rect() {
1432        let f =
1433            BufReader::new(std::fs::File::open("tests/images/bmp/images/Core_8_Bit.bmp").unwrap());
1434        let mut decoder = BmpDecoder::new(f).unwrap();
1435
1436        let mut buf: Vec<u8> = vec![0; 8 * 8 * 3];
1437        decoder.read_rect(0, 0, 8, 8, &mut buf, 8 * 3).unwrap();
1438    }
1439
1440    #[test]
1441    fn read_rle_too_short() {
1442        let data = vec![
1443            0x42, 0x4d, 0x04, 0xee, 0xfe, 0xff, 0xff, 0x10, 0xff, 0x00, 0x04, 0x00, 0x00, 0x00,
1444            0x7c, 0x00, 0x00, 0x00, 0x0c, 0x41, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x01, 0x00,
1445            0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1446            0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x21,
1447            0xff, 0x00, 0x66, 0x61, 0x72, 0x62, 0x66, 0x65, 0x6c, 0x64, 0x00, 0x00, 0x00, 0x00,
1448            0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1449            0xff, 0xd8, 0xff, 0x00, 0x00, 0x19, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1450            0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0xff, 0x00, 0x00, 0x00,
1451            0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
1452            0x00, 0x00, 0x00, 0x2d, 0x31, 0x31, 0x35, 0x36, 0x00, 0xff, 0x00, 0x00, 0x52, 0x3a,
1453            0x37, 0x30, 0x7e, 0x71, 0x63, 0x91, 0x5a, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
1454            0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
1455            0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x35, 0x37, 0x00, 0xff, 0x00, 0x00, 0x52,
1456            0x3a, 0x37, 0x30, 0x7e, 0x71, 0x63, 0x91, 0x5a, 0x04, 0x05, 0x3c, 0x00, 0x00, 0x11,
1457            0x00, 0x5d, 0x7a, 0x82, 0xb7, 0xca, 0x2d, 0x31, 0xff, 0xff, 0xc7, 0x95, 0x33, 0x2e,
1458            0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00,
1459            0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x66, 0x00, 0x4d,
1460            0x4d, 0x00, 0x2a, 0x00,
1461        ];
1462
1463        let decoder = BmpDecoder::new(Cursor::new(&data)).unwrap();
1464        let mut buf = vec![0; usize::try_from(decoder.total_bytes()).unwrap()];
1465        assert!(decoder.read_image(&mut buf).is_ok());
1466    }
1467
1468    #[test]
1469    fn test_no_header() {
1470        let tests = [
1471            "Info_R8_G8_B8.bmp",
1472            "Info_A8_R8_G8_B8.bmp",
1473            "Info_8_Bit.bmp",
1474            "Info_4_Bit.bmp",
1475            "Info_1_Bit.bmp",
1476        ];
1477
1478        for name in &tests {
1479            let path = format!("tests/images/bmp/images/{name}");
1480            let ref_img = crate::open(&path).unwrap();
1481            let mut data = std::fs::read(&path).unwrap();
1482            // skip the BITMAPFILEHEADER
1483            let slice = &mut data[14..];
1484            let decoder = BmpDecoder::new_without_file_header(Cursor::new(slice)).unwrap();
1485            let no_hdr_img = crate::DynamicImage::from_decoder(decoder).unwrap();
1486            assert_eq!(ref_img, no_hdr_img);
1487        }
1488    }
1489}