Coverage Report

Created: 2025-11-09 06:56

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