1use std::cmp::{self, Ordering};
2use std::io::{self, Cursor, Read, Seek, SeekFrom};
3use std::iter::{repeat, Rev};
4use std::marker::PhantomData;
5use std::slice::ChunksMut;
6use std::{error, fmt, mem};
7
8use byteorder::{LittleEndian, ReadBytesExt};
9
10use crate::color::ColorType;
11use crate::error::{
12 DecodingError, ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind,
13};
14use crate::image::{self, ImageDecoder, ImageDecoderRect, ImageFormat, Progress};
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
62const 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) => chunks.next(),
112 Chunker::FromBottom(ref mut chunks) => chunks.next(),
113 }
114 }
115}
116
117#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
119enum DecoderError {
120 CorruptRleData,
122
123 BitfieldMaskNonContiguous,
125 BitfieldMaskInvalid,
127 BitfieldMaskMissing(u32),
129 BitfieldMasksMissing(u32),
131
132 BmpSignatureInvalid,
134 MoreThanOnePlane,
136 InvalidChannelWidth(ChannelWidthError, u16),
138
139 NegativeWidth(i32),
141 ImageTooLarge(i32, i32),
143 InvalidHeight,
147
148 ImageTypeInvalidForTopDown(u32),
150 ImageTypeUnknown(u32),
152
153 HeaderTooSmall(u32),
155
156 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 {}-bit bitfield mask", bb))
171 }
172 DecoderError::BitfieldMasksMissing(bb) => {
173 f.write_fmt(format_args!("Missing {}-bit bitfield masks", bb))
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 ({}, {}) > soft limit of {})",
183 w, h, MAX_WIDTH_HEIGHT
184 )),
185 DecoderError::InvalidHeight => f.write_str("Invalid height"),
186 DecoderError::ImageTypeInvalidForTopDown(tp) => f.write_fmt(format_args!(
187 "Invalid image type {} for top-down image.",
188 tp
189 )),
190 DecoderError::ImageTypeUnknown(tp) => {
191 f.write_fmt(format_args!("Unknown image compression type {}", tp))
192 }
193 DecoderError::HeaderTooSmall(s) => {
194 f.write_fmt(format_args!("Bitmap header too small ({} bytes)", s))
195 }
196 DecoderError::PaletteSizeExceeded {
197 colors_used,
198 bit_count,
199 } => f.write_fmt(format_args!(
200 "Palette size {} exceeds maximum size for BMP with bit count of {}",
201 colors_used, 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#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
217enum ChannelWidthError {
218 Rgb,
220 Rle8,
222 Rle4,
224 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
239fn 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 ({}x{} w/{} channels) are too large",
249 width, length, channels
250 )),
251 ))
252 })
253}
254
255fn num_bytes(width: i32, length: i32, channels: usize) -> Option<usize> {
258 if width <= 0 || length <= 0 {
259 None
260 } else {
261 match channels.checked_mul(width as usize) {
262 Some(n) => n.checked_mul(length as usize),
263 None => None,
264 }
265 }
266}
267
268fn with_rows<F>(
271 buffer: &mut [u8],
272 width: i32,
273 height: i32,
274 channels: usize,
275 top_down: bool,
276 mut func: F,
277) -> io::Result<()>
278where
279 F: FnMut(&mut [u8]) -> io::Result<()>,
280{
281 let row_width = channels.checked_mul(width as usize).unwrap();
284 let full_image_size = row_width.checked_mul(height as usize).unwrap();
285 assert_eq!(buffer.len(), full_image_size);
286
287 if !top_down {
288 for row in buffer.chunks_mut(row_width).rev() {
289 func(row)?;
290 }
291 } else {
292 for row in buffer.chunks_mut(row_width) {
293 func(row)?;
294 }
295 }
296 Ok(())
297}
298
299fn set_8bit_pixel_run<'a, T: Iterator<Item = &'a u8>>(
300 pixel_iter: &mut ChunksMut<u8>,
301 palette: &[[u8; 3]],
302 indices: T,
303 n_pixels: usize,
304) -> bool {
305 for idx in indices.take(n_pixels) {
306 if let Some(pixel) = pixel_iter.next() {
307 let rgb = palette[*idx as usize];
308 pixel[0] = rgb[0];
309 pixel[1] = rgb[1];
310 pixel[2] = rgb[2];
311 } else {
312 return false;
313 }
314 }
315 true
316}
317
318fn set_4bit_pixel_run<'a, T: Iterator<Item = &'a u8>>(
319 pixel_iter: &mut ChunksMut<u8>,
320 palette: &[[u8; 3]],
321 indices: T,
322 mut n_pixels: usize,
323) -> bool {
324 for idx in indices {
325 macro_rules! set_pixel {
326 ($i:expr) => {
327 if n_pixels == 0 {
328 break;
329 }
330 if let Some(pixel) = pixel_iter.next() {
331 let rgb = palette[$i as usize];
332 pixel[0] = rgb[0];
333 pixel[1] = rgb[1];
334 pixel[2] = rgb[2];
335 } else {
336 return false;
337 }
338 n_pixels -= 1;
339 };
340 }
341 set_pixel!(idx >> 4);
342 set_pixel!(idx & 0xf);
343 }
344 true
345}
346
347#[rustfmt::skip]
348fn set_2bit_pixel_run<'a, T: Iterator<Item = &'a u8>>(
349 pixel_iter: &mut ChunksMut<u8>,
350 palette: &[[u8; 3]],
351 indices: T,
352 mut n_pixels: usize,
353) -> bool {
354 for idx in indices {
355 macro_rules! set_pixel {
356 ($i:expr) => {
357 if n_pixels == 0 {
358 break;
359 }
360 if let Some(pixel) = pixel_iter.next() {
361 let rgb = palette[$i as usize];
362 pixel[0] = rgb[0];
363 pixel[1] = rgb[1];
364 pixel[2] = rgb[2];
365 } else {
366 return false;
367 }
368 n_pixels -= 1;
369 };
370 }
371 set_pixel!((idx >> 6) & 0x3u8);
372 set_pixel!((idx >> 4) & 0x3u8);
373 set_pixel!((idx >> 2) & 0x3u8);
374 set_pixel!( idx & 0x3u8);
375 }
376 true
377}
378
379fn set_1bit_pixel_run<'a, T: Iterator<Item = &'a u8>>(
380 pixel_iter: &mut ChunksMut<u8>,
381 palette: &[[u8; 3]],
382 indices: T,
383) {
384 for idx in indices {
385 let mut bit = 0x80;
386 loop {
387 if let Some(pixel) = pixel_iter.next() {
388 let rgb = palette[((idx & bit) != 0) as usize];
389 pixel[0] = rgb[0];
390 pixel[1] = rgb[1];
391 pixel[2] = rgb[2];
392 } else {
393 return;
394 }
395
396 bit >>= 1;
397 if bit == 0 {
398 break;
399 }
400 }
401 }
402}
403
404#[derive(PartialEq, Eq)]
405struct Bitfield {
406 shift: u32,
407 len: u32,
408}
409
410impl Bitfield {
411 fn from_mask(mask: u32, max_len: u32) -> ImageResult<Bitfield> {
412 if mask == 0 {
413 return Ok(Bitfield { shift: 0, len: 0 });
414 }
415 let mut shift = mask.trailing_zeros();
416 let mut len = (!(mask >> shift)).trailing_zeros();
417 if len != mask.count_ones() {
418 return Err(DecoderError::BitfieldMaskNonContiguous.into());
419 }
420 if len + shift > max_len {
421 return Err(DecoderError::BitfieldMaskInvalid.into());
422 }
423 if len > 8 {
424 shift += len - 8;
425 len = 8;
426 }
427 Ok(Bitfield { shift, len })
428 }
429
430 fn read(&self, data: u32) -> u8 {
431 let data = data >> self.shift;
432 match self.len {
433 1 => ((data & 0b1) * 0xff) as u8,
434 2 => ((data & 0b11) * 0x55) as u8,
435 3 => LOOKUP_TABLE_3_BIT_TO_8_BIT[(data & 0b00_0111) as usize],
436 4 => LOOKUP_TABLE_4_BIT_TO_8_BIT[(data & 0b00_1111) as usize],
437 5 => LOOKUP_TABLE_5_BIT_TO_8_BIT[(data & 0b01_1111) as usize],
438 6 => LOOKUP_TABLE_6_BIT_TO_8_BIT[(data & 0b11_1111) as usize],
439 7 => ((data & 0x7f) << 1 | (data & 0x7f) >> 6) as u8,
440 8 => (data & 0xff) as u8,
441 _ => panic!(),
442 }
443 }
444}
445
446#[derive(PartialEq, Eq)]
447struct Bitfields {
448 r: Bitfield,
449 g: Bitfield,
450 b: Bitfield,
451 a: Bitfield,
452}
453
454impl Bitfields {
455 fn from_mask(
456 r_mask: u32,
457 g_mask: u32,
458 b_mask: u32,
459 a_mask: u32,
460 max_len: u32,
461 ) -> ImageResult<Bitfields> {
462 let bitfields = Bitfields {
463 r: Bitfield::from_mask(r_mask, max_len)?,
464 g: Bitfield::from_mask(g_mask, max_len)?,
465 b: Bitfield::from_mask(b_mask, max_len)?,
466 a: Bitfield::from_mask(a_mask, max_len)?,
467 };
468 if bitfields.r.len == 0 || bitfields.g.len == 0 || bitfields.b.len == 0 {
469 return Err(DecoderError::BitfieldMaskMissing(max_len).into());
470 }
471 Ok(bitfields)
472 }
473}
474
475pub struct BmpDecoder<R> {
477 reader: R,
478
479 bmp_header_type: BMPHeaderType,
480 indexed_color: bool,
481
482 width: i32,
483 height: i32,
484 data_offset: u64,
485 top_down: bool,
486 no_file_header: bool,
487 add_alpha_channel: bool,
488 has_loaded_metadata: bool,
489 image_type: ImageType,
490
491 bit_count: u16,
492 colors_used: u32,
493 palette: Option<Vec<[u8; 3]>>,
494 bitfields: Option<Bitfields>,
495}
496
497enum RLEInsn {
498 EndOfFile,
499 EndOfRow,
500 Delta(u8, u8),
501 Absolute(u8, Vec<u8>),
502 PixelRun(u8, u8),
503}
504
505impl<R: Read + Seek> BmpDecoder<R> {
506 fn new_decoder(reader: R) -> BmpDecoder<R> {
507 BmpDecoder {
508 reader,
509
510 bmp_header_type: BMPHeaderType::Info,
511 indexed_color: false,
512
513 width: 0,
514 height: 0,
515 data_offset: 0,
516 top_down: false,
517 no_file_header: false,
518 add_alpha_channel: false,
519 has_loaded_metadata: false,
520 image_type: ImageType::Palette,
521
522 bit_count: 0,
523 colors_used: 0,
524 palette: None,
525 bitfields: None,
526 }
527 }
528
529 pub fn new(reader: R) -> ImageResult<BmpDecoder<R>> {
531 let mut decoder = Self::new_decoder(reader);
532 decoder.read_metadata()?;
533 Ok(decoder)
534 }
535
536 pub fn new_without_file_header(reader: R) -> ImageResult<BmpDecoder<R>> {
540 let mut decoder = Self::new_decoder(reader);
541 decoder.no_file_header = true;
542 decoder.read_metadata()?;
543 Ok(decoder)
544 }
545
546 #[cfg(feature = "ico")]
547 pub(crate) fn new_with_ico_format(reader: R) -> ImageResult<BmpDecoder<R>> {
548 let mut decoder = Self::new_decoder(reader);
549 decoder.read_metadata_in_ico_format()?;
550 Ok(decoder)
551 }
552
553 pub fn set_indexed_color(&mut self, indexed_color: bool) {
556 self.indexed_color = indexed_color;
557 }
558
559 #[cfg(feature = "ico")]
560 pub(crate) fn reader(&mut self) -> &mut R {
561 &mut self.reader
562 }
563
564 fn read_file_header(&mut self) -> ImageResult<()> {
565 if self.no_file_header {
566 return Ok(());
567 }
568 let mut signature = [0; 2];
569 self.reader.read_exact(&mut signature)?;
570
571 if signature != b"BM"[..] {
572 return Err(DecoderError::BmpSignatureInvalid.into());
573 }
574
575 self.reader.read_u32::<LittleEndian>()?;
578 self.reader.read_u32::<LittleEndian>()?;
579
580 self.data_offset = u64::from(self.reader.read_u32::<LittleEndian>()?);
581
582 Ok(())
583 }
584
585 fn read_bitmap_core_header(&mut self) -> ImageResult<()> {
589 self.width = i32::from(self.reader.read_u16::<LittleEndian>()?);
592 self.height = i32::from(self.reader.read_u16::<LittleEndian>()?);
593
594 check_for_overflow(self.width, self.height, self.num_channels())?;
595
596 if self.reader.read_u16::<LittleEndian>()? != 1 {
598 return Err(DecoderError::MoreThanOnePlane.into());
599 }
600
601 self.bit_count = self.reader.read_u16::<LittleEndian>()?;
602 self.image_type = match self.bit_count {
603 1 | 4 | 8 => ImageType::Palette,
604 24 => ImageType::RGB24,
605 _ => {
606 return Err(DecoderError::InvalidChannelWidth(
607 ChannelWidthError::Rgb,
608 self.bit_count,
609 )
610 .into())
611 }
612 };
613
614 Ok(())
615 }
616
617 fn read_bitmap_info_header(&mut self) -> ImageResult<()> {
622 self.width = self.reader.read_i32::<LittleEndian>()?;
623 self.height = self.reader.read_i32::<LittleEndian>()?;
624
625 if self.width < 0 {
627 return Err(DecoderError::NegativeWidth(self.width).into());
628 } else if self.width > MAX_WIDTH_HEIGHT || self.height > MAX_WIDTH_HEIGHT {
629 return Err(DecoderError::ImageTooLarge(self.width, self.height).into());
632 }
633
634 if self.height == i32::min_value() {
635 return Err(DecoderError::InvalidHeight.into());
636 }
637
638 if self.height < 0 {
640 self.height *= -1;
641 self.top_down = true;
642 }
643
644 check_for_overflow(self.width, self.height, self.num_channels())?;
645
646 if self.reader.read_u16::<LittleEndian>()? != 1 {
648 return Err(DecoderError::MoreThanOnePlane.into());
649 }
650
651 self.bit_count = self.reader.read_u16::<LittleEndian>()?;
652 let image_type_u32 = self.reader.read_u32::<LittleEndian>()?;
653
654 if self.top_down && image_type_u32 != 0 && image_type_u32 != 3 {
656 return Err(DecoderError::ImageTypeInvalidForTopDown(image_type_u32).into());
657 }
658 self.image_type = match image_type_u32 {
659 0 => match self.bit_count {
660 1 | 2 | 4 | 8 => ImageType::Palette,
661 16 => ImageType::RGB16,
662 24 => ImageType::RGB24,
663 32 if self.add_alpha_channel => ImageType::RGBA32,
664 32 => ImageType::RGB32,
665 _ => {
666 return Err(DecoderError::InvalidChannelWidth(
667 ChannelWidthError::Rgb,
668 self.bit_count,
669 )
670 .into())
671 }
672 },
673 1 => match self.bit_count {
674 8 => ImageType::RLE8,
675 _ => {
676 return Err(DecoderError::InvalidChannelWidth(
677 ChannelWidthError::Rle8,
678 self.bit_count,
679 )
680 .into())
681 }
682 },
683 2 => match self.bit_count {
684 4 => ImageType::RLE4,
685 _ => {
686 return Err(DecoderError::InvalidChannelWidth(
687 ChannelWidthError::Rle4,
688 self.bit_count,
689 )
690 .into())
691 }
692 },
693 3 => match self.bit_count {
694 16 => ImageType::Bitfields16,
695 32 => ImageType::Bitfields32,
696 _ => {
697 return Err(DecoderError::InvalidChannelWidth(
698 ChannelWidthError::Bitfields,
699 self.bit_count,
700 )
701 .into())
702 }
703 },
704 4 => {
705 return Err(ImageError::Unsupported(
707 UnsupportedError::from_format_and_kind(
708 ImageFormat::Bmp.into(),
709 UnsupportedErrorKind::GenericFeature("JPEG compression".to_owned()),
710 ),
711 ));
712 }
713 5 => {
714 return Err(ImageError::Unsupported(
716 UnsupportedError::from_format_and_kind(
717 ImageFormat::Bmp.into(),
718 UnsupportedErrorKind::GenericFeature("PNG compression".to_owned()),
719 ),
720 ));
721 }
722 11..=13 => {
723 return Err(ImageError::Unsupported(
725 UnsupportedError::from_format_and_kind(
726 ImageFormat::Bmp.into(),
727 UnsupportedErrorKind::GenericFeature("CMYK format".to_owned()),
728 ),
729 ));
730 }
731 _ => {
732 return Err(DecoderError::ImageTypeUnknown(image_type_u32).into());
734 }
735 };
736
737 self.reader.read_u32::<LittleEndian>()?;
742 self.reader.read_u32::<LittleEndian>()?;
743 self.reader.read_u32::<LittleEndian>()?;
744
745 self.colors_used = self.reader.read_u32::<LittleEndian>()?;
746
747 self.reader.read_u32::<LittleEndian>()?;
750
751 Ok(())
752 }
753
754 fn read_bitmasks(&mut self) -> ImageResult<()> {
755 let r_mask = self.reader.read_u32::<LittleEndian>()?;
756 let g_mask = self.reader.read_u32::<LittleEndian>()?;
757 let b_mask = self.reader.read_u32::<LittleEndian>()?;
758
759 let a_mask = match self.bmp_header_type {
760 BMPHeaderType::V3 | BMPHeaderType::V4 | BMPHeaderType::V5 => {
761 self.reader.read_u32::<LittleEndian>()?
762 }
763 _ => 0,
764 };
765
766 self.bitfields = match self.image_type {
767 ImageType::Bitfields16 => {
768 Some(Bitfields::from_mask(r_mask, g_mask, b_mask, a_mask, 16)?)
769 }
770 ImageType::Bitfields32 => {
771 Some(Bitfields::from_mask(r_mask, g_mask, b_mask, a_mask, 32)?)
772 }
773 _ => None,
774 };
775
776 if self.bitfields.is_some() && a_mask != 0 {
777 self.add_alpha_channel = true;
778 }
779
780 Ok(())
781 }
782
783 fn read_metadata(&mut self) -> ImageResult<()> {
784 if !self.has_loaded_metadata {
785 self.read_file_header()?;
786 let bmp_header_offset = self.reader.stream_position()?;
787 let bmp_header_size = self.reader.read_u32::<LittleEndian>()?;
788 let bmp_header_end = bmp_header_offset + u64::from(bmp_header_size);
789
790 self.bmp_header_type = match bmp_header_size {
791 BITMAPCOREHEADER_SIZE => BMPHeaderType::Core,
792 BITMAPINFOHEADER_SIZE => BMPHeaderType::Info,
793 BITMAPV2HEADER_SIZE => BMPHeaderType::V2,
794 BITMAPV3HEADER_SIZE => BMPHeaderType::V3,
795 BITMAPV4HEADER_SIZE => BMPHeaderType::V4,
796 BITMAPV5HEADER_SIZE => BMPHeaderType::V5,
797 _ if bmp_header_size < BITMAPCOREHEADER_SIZE => {
798 return Err(DecoderError::HeaderTooSmall(bmp_header_size).into());
800 }
801 _ => {
802 return Err(ImageError::Unsupported(
803 UnsupportedError::from_format_and_kind(
804 ImageFormat::Bmp.into(),
805 UnsupportedErrorKind::GenericFeature(format!(
806 "Unknown bitmap header type (size={})",
807 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 match self.image_type {
828 ImageType::Bitfields16 | ImageType::Bitfields32 => self.read_bitmasks()?,
829 _ => {}
830 };
831
832 self.reader.seek(SeekFrom::Start(bmp_header_end))?;
833
834 match self.image_type {
835 ImageType::Palette | ImageType::RLE4 | ImageType::RLE8 => self.read_palette()?,
836 _ => {}
837 };
838
839 if self.no_file_header {
840 self.data_offset = self.reader.stream_position()?;
842 }
843
844 self.has_loaded_metadata = true;
845 }
846 Ok(())
847 }
848
849 #[cfg(feature = "ico")]
850 #[doc(hidden)]
851 pub fn read_metadata_in_ico_format(&mut self) -> ImageResult<()> {
852 self.no_file_header = true;
853 self.add_alpha_channel = true;
854 self.read_metadata()?;
855
856 self.height /= 2;
859 Ok(())
860 }
861
862 fn get_palette_size(&mut self) -> ImageResult<usize> {
863 match self.colors_used {
864 0 => Ok(1 << self.bit_count),
865 _ => {
866 if self.colors_used > 1 << self.bit_count {
867 return Err(DecoderError::PaletteSizeExceeded {
868 colors_used: self.colors_used,
869 bit_count: self.bit_count,
870 }
871 .into());
872 }
873 Ok(self.colors_used as usize)
874 }
875 }
876 }
877
878 fn bytes_per_color(&self) -> usize {
879 match self.bmp_header_type {
880 BMPHeaderType::Core => 3,
881 _ => 4,
882 }
883 }
884
885 fn read_palette(&mut self) -> ImageResult<()> {
886 const MAX_PALETTE_SIZE: usize = 256; let bytes_per_color = self.bytes_per_color();
889 let palette_size = self.get_palette_size()?;
890 let max_length = MAX_PALETTE_SIZE * bytes_per_color;
891
892 let length = palette_size * bytes_per_color;
893 let mut buf = Vec::with_capacity(max_length);
894
895 buf.resize(cmp::min(length, max_length), 0);
899 self.reader.by_ref().read_exact(&mut buf)?;
900
901 match length.cmp(&max_length) {
904 Ordering::Greater => {
905 self.reader
906 .seek(SeekFrom::Current((length - max_length) as i64))?;
907 }
908 Ordering::Less => buf.resize(max_length, 0),
909 Ordering::Equal => (),
910 }
911
912 let p: Vec<[u8; 3]> = (0..MAX_PALETTE_SIZE)
913 .map(|i| {
914 let b = buf[bytes_per_color * i];
915 let g = buf[bytes_per_color * i + 1];
916 let r = buf[bytes_per_color * i + 2];
917 [r, g, b]
918 })
919 .collect();
920
921 self.palette = Some(p);
922
923 Ok(())
924 }
925
926 pub fn get_palette(&self) -> Option<&[[u8; 3]]> {
928 self.palette.as_ref().map(|vec| &vec[..])
929 }
930
931 fn num_channels(&self) -> usize {
932 if self.indexed_color {
933 1
934 } else if self.add_alpha_channel {
935 4
936 } else {
937 3
938 }
939 }
940
941 fn rows<'a>(&self, pixel_data: &'a mut [u8]) -> RowIterator<'a> {
942 let stride = self.width as usize * self.num_channels();
943 if self.top_down {
944 RowIterator {
945 chunks: Chunker::FromTop(pixel_data.chunks_mut(stride)),
946 }
947 } else {
948 RowIterator {
949 chunks: Chunker::FromBottom(pixel_data.chunks_mut(stride).rev()),
950 }
951 }
952 }
953
954 fn read_palettized_pixel_data(&mut self, buf: &mut [u8]) -> ImageResult<()> {
955 let num_channels = self.num_channels();
956 let row_byte_length = ((i32::from(self.bit_count) * self.width + 31) / 32 * 4) as usize;
957 let mut indices = vec![0; row_byte_length];
958 let palette = self.palette.as_ref().unwrap();
959 let bit_count = self.bit_count;
960 let reader = &mut self.reader;
961 let width = self.width as usize;
962 let skip_palette = self.indexed_color;
963
964 reader.seek(SeekFrom::Start(self.data_offset))?;
965
966 if num_channels == 4 {
967 buf.chunks_exact_mut(4).for_each(|c| c[3] = 0xFF);
968 }
969
970 with_rows(
971 buf,
972 self.width,
973 self.height,
974 num_channels,
975 self.top_down,
976 |row| {
977 reader.read_exact(&mut indices)?;
978 if skip_palette {
979 row.clone_from_slice(&indices[0..width]);
980 } else {
981 let mut pixel_iter = row.chunks_mut(num_channels);
982 match bit_count {
983 1 => {
984 set_1bit_pixel_run(&mut pixel_iter, palette, indices.iter());
985 }
986 2 => {
987 set_2bit_pixel_run(&mut pixel_iter, palette, indices.iter(), width);
988 }
989 4 => {
990 set_4bit_pixel_run(&mut pixel_iter, palette, indices.iter(), width);
991 }
992 8 => {
993 set_8bit_pixel_run(&mut pixel_iter, palette, indices.iter(), width);
994 }
995 _ => panic!(),
996 };
997 }
998 Ok(())
999 },
1000 )?;
1001
1002 Ok(())
1003 }
1004
1005 fn read_16_bit_pixel_data(
1006 &mut self,
1007 buf: &mut [u8],
1008 bitfields: Option<&Bitfields>,
1009 ) -> ImageResult<()> {
1010 let num_channels = self.num_channels();
1011 let row_padding_len = self.width as usize % 2 * 2;
1012 let row_padding = &mut [0; 2][..row_padding_len];
1013 let bitfields = match bitfields {
1014 Some(b) => b,
1015 None => self.bitfields.as_ref().unwrap(),
1016 };
1017 let reader = &mut self.reader;
1018
1019 reader.seek(SeekFrom::Start(self.data_offset))?;
1020
1021 with_rows(
1022 buf,
1023 self.width,
1024 self.height,
1025 num_channels,
1026 self.top_down,
1027 |row| {
1028 for pixel in row.chunks_mut(num_channels) {
1029 let data = u32::from(reader.read_u16::<LittleEndian>()?);
1030
1031 pixel[0] = bitfields.r.read(data);
1032 pixel[1] = bitfields.g.read(data);
1033 pixel[2] = bitfields.b.read(data);
1034 if num_channels == 4 {
1035 if bitfields.a.len != 0 {
1036 pixel[3] = bitfields.a.read(data);
1037 } else {
1038 pixel[3] = 0xFF;
1039 }
1040 }
1041 }
1042 reader.read_exact(row_padding)
1043 },
1044 )?;
1045
1046 Ok(())
1047 }
1048
1049 fn read_32_bit_pixel_data(&mut self, buf: &mut [u8]) -> ImageResult<()> {
1051 let num_channels = self.num_channels();
1052
1053 let bitfields = self.bitfields.as_ref().unwrap();
1054
1055 let reader = &mut self.reader;
1056 reader.seek(SeekFrom::Start(self.data_offset))?;
1057
1058 with_rows(
1059 buf,
1060 self.width,
1061 self.height,
1062 num_channels,
1063 self.top_down,
1064 |row| {
1065 for pixel in row.chunks_mut(num_channels) {
1066 let data = reader.read_u32::<LittleEndian>()?;
1067
1068 pixel[0] = bitfields.r.read(data);
1069 pixel[1] = bitfields.g.read(data);
1070 pixel[2] = bitfields.b.read(data);
1071 if num_channels == 4 {
1072 if bitfields.a.len != 0 {
1073 pixel[3] = bitfields.a.read(data);
1074 } else {
1075 pixel[3] = 0xff;
1076 }
1077 }
1078 }
1079 Ok(())
1080 },
1081 )?;
1082
1083 Ok(())
1084 }
1085
1086 fn read_full_byte_pixel_data(
1088 &mut self,
1089 buf: &mut [u8],
1090 format: &FormatFullBytes,
1091 ) -> ImageResult<()> {
1092 let num_channels = self.num_channels();
1093 let row_padding_len = match *format {
1094 FormatFullBytes::RGB24 => (4 - (self.width as usize * 3) % 4) % 4,
1095 _ => 0,
1096 };
1097 let row_padding = &mut [0; 4][..row_padding_len];
1098
1099 self.reader.seek(SeekFrom::Start(self.data_offset))?;
1100
1101 let reader = &mut self.reader;
1102
1103 with_rows(
1104 buf,
1105 self.width,
1106 self.height,
1107 num_channels,
1108 self.top_down,
1109 |row| {
1110 for pixel in row.chunks_mut(num_channels) {
1111 if *format == FormatFullBytes::Format888 {
1112 reader.read_u8()?;
1113 }
1114
1115 reader.read_exact(&mut pixel[0..3])?;
1119 pixel[0..3].reverse();
1120
1121 if *format == FormatFullBytes::RGB32 {
1122 reader.read_u8()?;
1123 }
1124
1125 if *format == FormatFullBytes::RGBA32 {
1127 reader.read_exact(&mut pixel[3..4])?;
1128 } else if num_channels == 4 {
1129 pixel[3] = 0xFF;
1130 }
1131 }
1132 reader.read_exact(row_padding)
1133 },
1134 )?;
1135
1136 Ok(())
1137 }
1138
1139 fn read_rle_data(&mut self, buf: &mut [u8], image_type: ImageType) -> ImageResult<()> {
1140 self.reader.seek(SeekFrom::Start(self.data_offset))?;
1142
1143 let num_channels = self.num_channels();
1144 let p = self.palette.as_ref().unwrap();
1145
1146 let mut row_iter = self.rows(buf);
1151
1152 while let Some(row) = row_iter.next() {
1153 let mut pixel_iter = row.chunks_mut(num_channels);
1154
1155 let mut x = 0;
1156 loop {
1157 let instruction = {
1158 let control_byte = self.reader.read_u8()?;
1159 match control_byte {
1160 RLE_ESCAPE => {
1161 let op = self.reader.read_u8()?;
1162
1163 match op {
1164 RLE_ESCAPE_EOL => RLEInsn::EndOfRow,
1165 RLE_ESCAPE_EOF => RLEInsn::EndOfFile,
1166 RLE_ESCAPE_DELTA => {
1167 let xdelta = self.reader.read_u8()?;
1168 let ydelta = self.reader.read_u8()?;
1169 RLEInsn::Delta(xdelta, ydelta)
1170 }
1171 _ => {
1172 let mut length = op as usize;
1173 if self.image_type == ImageType::RLE4 {
1174 length = (length + 1) / 2;
1175 }
1176 length += length & 1;
1177 let mut buffer = vec![0; length];
1178 self.reader.read_exact(&mut buffer)?;
1179 RLEInsn::Absolute(op, buffer)
1180 }
1181 }
1182 }
1183 _ => {
1184 let palette_index = self.reader.read_u8()?;
1185 RLEInsn::PixelRun(control_byte, palette_index)
1186 }
1187 }
1188 };
1189
1190 match instruction {
1191 RLEInsn::EndOfFile => {
1192 pixel_iter.for_each(|p| p.fill(0));
1193 row_iter.for_each(|r| r.fill(0));
1194 return Ok(());
1195 }
1196 RLEInsn::EndOfRow => {
1197 pixel_iter.for_each(|p| p.fill(0));
1198 break;
1199 }
1200 RLEInsn::Delta(x_delta, y_delta) => {
1201 if y_delta > 0 {
1208 pixel_iter.for_each(|p| p.fill(0));
1210
1211 for _ in 1..y_delta {
1213 let row = row_iter.next().ok_or(DecoderError::CorruptRleData)?;
1214 row.fill(0);
1215 }
1216
1217 pixel_iter = row_iter
1219 .next()
1220 .ok_or(DecoderError::CorruptRleData)?
1221 .chunks_mut(num_channels);
1222
1223 for _ in 0..x {
1225 pixel_iter
1226 .next()
1227 .ok_or(DecoderError::CorruptRleData)?
1228 .fill(0);
1229 }
1230 }
1231
1232 for _ in 0..x_delta {
1233 let pixel = pixel_iter.next().ok_or(DecoderError::CorruptRleData)?;
1234 pixel.fill(0);
1235 }
1236 x += x_delta as usize;
1237 }
1238 RLEInsn::Absolute(length, indices) => {
1239 match image_type {
1243 ImageType::RLE8 => {
1244 if !set_8bit_pixel_run(
1245 &mut pixel_iter,
1246 p,
1247 indices.iter(),
1248 length as usize,
1249 ) {
1250 return Err(DecoderError::CorruptRleData.into());
1251 }
1252 }
1253 ImageType::RLE4 => {
1254 if !set_4bit_pixel_run(
1255 &mut pixel_iter,
1256 p,
1257 indices.iter(),
1258 length as usize,
1259 ) {
1260 return Err(DecoderError::CorruptRleData.into());
1261 }
1262 }
1263 _ => unreachable!(),
1264 }
1265 x += length as usize;
1266 }
1267 RLEInsn::PixelRun(n_pixels, palette_index) => {
1268 match image_type {
1272 ImageType::RLE8 => {
1273 if !set_8bit_pixel_run(
1274 &mut pixel_iter,
1275 p,
1276 repeat(&palette_index),
1277 n_pixels as usize,
1278 ) {
1279 return Err(DecoderError::CorruptRleData.into());
1280 }
1281 }
1282 ImageType::RLE4 => {
1283 if !set_4bit_pixel_run(
1284 &mut pixel_iter,
1285 p,
1286 repeat(&palette_index),
1287 n_pixels as usize,
1288 ) {
1289 return Err(DecoderError::CorruptRleData.into());
1290 }
1291 }
1292 _ => unreachable!(),
1293 }
1294 x += n_pixels as usize;
1295 }
1296 }
1297 }
1298 }
1299
1300 Ok(())
1301 }
1302
1303 pub(crate) fn read_image_data(&mut self, buf: &mut [u8]) -> ImageResult<()> {
1306 match self.image_type {
1307 ImageType::Palette => self.read_palettized_pixel_data(buf),
1308 ImageType::RGB16 => self.read_16_bit_pixel_data(buf, Some(&R5_G5_B5_COLOR_MASK)),
1309 ImageType::RGB24 => self.read_full_byte_pixel_data(buf, &FormatFullBytes::RGB24),
1310 ImageType::RGB32 => self.read_full_byte_pixel_data(buf, &FormatFullBytes::RGB32),
1311 ImageType::RGBA32 => self.read_full_byte_pixel_data(buf, &FormatFullBytes::RGBA32),
1312 ImageType::RLE8 => self.read_rle_data(buf, ImageType::RLE8),
1313 ImageType::RLE4 => self.read_rle_data(buf, ImageType::RLE4),
1314 ImageType::Bitfields16 => match self.bitfields {
1315 Some(_) => self.read_16_bit_pixel_data(buf, None),
1316 None => Err(DecoderError::BitfieldMasksMissing(16).into()),
1317 },
1318 ImageType::Bitfields32 => match self.bitfields {
1319 Some(R8_G8_B8_COLOR_MASK) => {
1320 self.read_full_byte_pixel_data(buf, &FormatFullBytes::Format888)
1321 }
1322 Some(R8_G8_B8_A8_COLOR_MASK) => {
1323 self.read_full_byte_pixel_data(buf, &FormatFullBytes::RGBA32)
1324 }
1325 Some(_) => self.read_32_bit_pixel_data(buf),
1326 None => Err(DecoderError::BitfieldMasksMissing(32).into()),
1327 },
1328 }
1329 }
1330}
1331
1332pub struct BmpReader<R>(Cursor<Vec<u8>>, PhantomData<R>);
1334impl<R> Read for BmpReader<R> {
1335 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
1336 self.0.read(buf)
1337 }
1338 fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
1339 if self.0.position() == 0 && buf.is_empty() {
1340 mem::swap(buf, self.0.get_mut());
1341 Ok(buf.len())
1342 } else {
1343 self.0.read_to_end(buf)
1344 }
1345 }
1346}
1347
1348impl<'a, R: 'a + Read + Seek> ImageDecoder<'a> for BmpDecoder<R> {
1349 type Reader = BmpReader<R>;
1350
1351 fn dimensions(&self) -> (u32, u32) {
1352 (self.width as u32, self.height as u32)
1353 }
1354
1355 fn color_type(&self) -> ColorType {
1356 if self.indexed_color {
1357 ColorType::L8
1358 } else if self.add_alpha_channel {
1359 ColorType::Rgba8
1360 } else {
1361 ColorType::Rgb8
1362 }
1363 }
1364
1365 fn into_reader(self) -> ImageResult<Self::Reader> {
1366 Ok(BmpReader(
1367 Cursor::new(image::decoder_to_vec(self)?),
1368 PhantomData,
1369 ))
1370 }
1371
1372 fn read_image(mut self, buf: &mut [u8]) -> ImageResult<()> {
1373 assert_eq!(u64::try_from(buf.len()), Ok(self.total_bytes()));
1374 self.read_image_data(buf)
1375 }
1376}
1377
1378impl<'a, R: 'a + Read + Seek> ImageDecoderRect<'a> for BmpDecoder<R> {
1379 fn read_rect_with_progress<F: Fn(Progress)>(
1380 &mut self,
1381 x: u32,
1382 y: u32,
1383 width: u32,
1384 height: u32,
1385 buf: &mut [u8],
1386 progress_callback: F,
1387 ) -> ImageResult<()> {
1388 let start = self.reader.stream_position()?;
1389 image::load_rect(
1390 x,
1391 y,
1392 width,
1393 height,
1394 buf,
1395 progress_callback,
1396 self,
1397 |_, _| Ok(()),
1398 |s, buf| s.read_image_data(buf),
1399 )?;
1400 self.reader.seek(SeekFrom::Start(start))?;
1401 Ok(())
1402 }
1403}
1404
1405#[cfg(test)]
1406mod test {
1407 use super::*;
1408
1409 #[test]
1410 fn test_bitfield_len() {
1411 for len in 1..9 {
1412 let bitfield = Bitfield { shift: 0, len };
1413 for i in 0..(1 << len) {
1414 let read = bitfield.read(i);
1415 let calc = (i as f64 / ((1 << len) - 1) as f64 * 255f64).round() as u8;
1416 if read != calc {
1417 println!("len:{} i:{} read:{} calc:{}", len, i, read, calc);
1418 }
1419 assert_eq!(read, calc);
1420 }
1421 }
1422 }
1423
1424 #[test]
1425 fn read_rect() {
1426 let f = std::fs::File::open("tests/images/bmp/images/Core_8_Bit.bmp").unwrap();
1427 let mut decoder = super::BmpDecoder::new(f).unwrap();
1428
1429 let mut buf: Vec<u8> = vec![0; 8 * 8 * 3];
1430 decoder.read_rect(0, 0, 8, 8, &mut buf).unwrap();
1431 }
1432
1433 #[test]
1434 fn read_rle_too_short() {
1435 let data = vec![
1436 0x42, 0x4d, 0x04, 0xee, 0xfe, 0xff, 0xff, 0x10, 0xff, 0x00, 0x04, 0x00, 0x00, 0x00,
1437 0x7c, 0x00, 0x00, 0x00, 0x0c, 0x41, 0x00, 0x00, 0x07, 0x10, 0x00, 0x00, 0x01, 0x00,
1438 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x00, 0x00,
1439 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xfe, 0x21,
1440 0xff, 0x00, 0x66, 0x61, 0x72, 0x62, 0x66, 0x65, 0x6c, 0x64, 0x00, 0x00, 0x00, 0x00,
1441 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1442 0xff, 0xd8, 0xff, 0x00, 0x00, 0x19, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1443 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfa, 0xff, 0x00, 0x00, 0x00,
1444 0x00, 0x01, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00,
1445 0x00, 0x00, 0x00, 0x2d, 0x31, 0x31, 0x35, 0x36, 0x00, 0xff, 0x00, 0x00, 0x52, 0x3a,
1446 0x37, 0x30, 0x7e, 0x71, 0x63, 0x91, 0x5a, 0x04, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
1447 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
1448 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x35, 0x37, 0x00, 0xff, 0x00, 0x00, 0x52,
1449 0x3a, 0x37, 0x30, 0x7e, 0x71, 0x63, 0x91, 0x5a, 0x04, 0x05, 0x3c, 0x00, 0x00, 0x11,
1450 0x00, 0x5d, 0x7a, 0x82, 0xb7, 0xca, 0x2d, 0x31, 0xff, 0xff, 0xc7, 0x95, 0x33, 0x2e,
1451 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x00,
1452 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x66, 0x00, 0x4d,
1453 0x4d, 0x00, 0x2a, 0x00,
1454 ];
1455
1456 let decoder = BmpDecoder::new(Cursor::new(&data)).unwrap();
1457 let mut buf = vec![0; usize::try_from(decoder.total_bytes()).unwrap()];
1458 assert!(decoder.read_image(&mut buf).is_ok());
1459 }
1460
1461 #[test]
1462 fn test_no_header() {
1463 let tests = [
1464 "Info_R8_G8_B8.bmp",
1465 "Info_A8_R8_G8_B8.bmp",
1466 "Info_8_Bit.bmp",
1467 "Info_4_Bit.bmp",
1468 "Info_1_Bit.bmp",
1469 ];
1470
1471 for name in &tests {
1472 let path = format!("tests/images/bmp/images/{name}");
1473 let ref_img = crate::open(&path).unwrap();
1474 let mut data = std::fs::read(&path).unwrap();
1475 let slice = &mut data[14..];
1477 let decoder = BmpDecoder::new_without_file_header(Cursor::new(slice)).unwrap();
1478 let no_hdr_img = crate::DynamicImage::from_decoder(decoder).unwrap();
1479 assert_eq!(ref_img, no_hdr_img);
1480 }
1481 }
1482}