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