@@ -5,13 +5,10 @@ use std::iter::{repeat, Rev};
55use std:: slice:: ChunksExactMut ;
66use std:: { error, fmt} ;
77
8- use byteorder_lite:: { LittleEndian , ReadBytesExt } ;
9-
108use crate :: color:: ColorType ;
119use crate :: error:: {
1210 DecodingError , ImageError , ImageResult , UnsupportedError , UnsupportedErrorKind ,
1311} ;
14- use crate :: io:: ReadExt ;
1512use crate :: { ImageDecoder , ImageFormat } ;
1613
1714const BITMAPCOREHEADER_SIZE : u32 = 12 ;
@@ -428,6 +425,21 @@ fn calculate_row_padding(bytes_per_row: usize) -> usize {
428425 ( 4 - ( bytes_per_row % 4 ) ) % 4
429426}
430427
428+ /// Allocate a row buffer with OOM protection.
429+ fn allocate_row_buffer ( size : usize ) -> ImageResult < Vec < u8 > > {
430+ let mut buffer = vec_try_with_capacity ( size) . map_err ( |_| {
431+ ImageError :: Unsupported ( UnsupportedError :: from_format_and_kind (
432+ ImageFormat :: Bmp . into ( ) ,
433+ UnsupportedErrorKind :: GenericFeature ( format ! (
434+ "Row buffer allocation ({} bytes) too large" ,
435+ size
436+ ) ) ,
437+ ) )
438+ } ) ?;
439+ buffer. resize ( size, 0 ) ;
440+ Ok ( buffer)
441+ }
442+
431443/// Convenience function to check if the combination of width, length and number of
432444/// channels would result in a buffer that would overflow.
433445fn check_for_overflow ( width : i32 , length : i32 , channels : usize ) -> ImageResult < ( ) > {
@@ -663,6 +675,54 @@ impl Bitfields {
663675 }
664676}
665677
678+ /// Helper to read RLE data using the already-buffered reader.
679+ /// Avoids double-buffering since BmpDecoder already requires BufRead.
680+ struct RleReader < ' a , R > {
681+ reader : & ' a mut R ,
682+ }
683+
684+ impl < ' a , R : BufRead > RleReader < ' a , R > {
685+ fn new ( reader : & ' a mut R ) -> Self {
686+ Self { reader }
687+ }
688+
689+ fn read_byte ( & mut self ) -> io:: Result < u8 > {
690+ let buf = self . reader . fill_buf ( ) ?;
691+ if buf. is_empty ( ) {
692+ return Err ( io:: Error :: new (
693+ io:: ErrorKind :: UnexpectedEof ,
694+ "unexpected end of RLE data" ,
695+ ) ) ;
696+ }
697+ let byte = buf[ 0 ] ;
698+ self . reader . consume ( 1 ) ;
699+ Ok ( byte)
700+ }
701+
702+ fn read_exact ( & mut self , buf : & mut [ u8 ] ) -> io:: Result < ( ) > {
703+ let mut remaining = buf. len ( ) ;
704+ let mut offset = 0 ;
705+
706+ while remaining > 0 {
707+ let available = self . reader . fill_buf ( ) ?;
708+ if available. is_empty ( ) {
709+ return Err ( io:: Error :: new (
710+ io:: ErrorKind :: UnexpectedEof ,
711+ "unexpected end of RLE data" ,
712+ ) ) ;
713+ }
714+
715+ let to_read = remaining. min ( available. len ( ) ) ;
716+ buf[ offset..offset + to_read] . copy_from_slice ( & available[ ..to_read] ) ;
717+ self . reader . consume ( to_read) ;
718+ offset += to_read;
719+ remaining -= to_read;
720+ }
721+
722+ Ok ( ( ) )
723+ }
724+ }
725+
666726/// A bmp decoder
667727pub struct BmpDecoder < R > {
668728 reader : R ,
@@ -686,11 +746,11 @@ pub struct BmpDecoder<R> {
686746 icc_profile : Option < Vec < u8 > > ,
687747}
688748
689- enum RLEInsn {
749+ enum RLEInsn < ' a > {
690750 EndOfFile ,
691751 EndOfRow ,
692752 Delta ( u8 , u8 ) ,
693- Absolute ( u8 , Vec < u8 > ) ,
753+ Absolute ( u8 , & ' a [ u8 ] ) ,
694754 PixelRun ( u8 , u8 ) ,
695755}
696756
@@ -1206,8 +1266,6 @@ impl<R: BufRead + Seek> BmpDecoder<R> {
12061266 bitfields : Option < & Bitfields > ,
12071267 ) -> ImageResult < ( ) > {
12081268 let num_channels = self . num_channels ( ) ;
1209- let row_padding_len = self . width as usize % 2 * 2 ;
1210- let row_padding = & mut [ 0 ; 2 ] [ ..row_padding_len] ;
12111269 let bitfields = match bitfields {
12121270 Some ( b) => b,
12131271 None => self . bitfields . as_ref ( ) . unwrap ( ) ,
@@ -1216,15 +1274,27 @@ impl<R: BufRead + Seek> BmpDecoder<R> {
12161274
12171275 reader. seek ( SeekFrom :: Start ( self . data_offset ) ) ?;
12181276
1277+ // Calculate row size in bytes (2 bytes per pixel + padding)
1278+ let row_data_len = self . width as usize * 2 ;
1279+ let row_padding_len = calculate_row_padding ( row_data_len) ;
1280+ let total_row_len = row_data_len + row_padding_len;
1281+
1282+ let mut row_buffer = allocate_row_buffer ( total_row_len) ?;
1283+
12191284 with_rows (
12201285 buf,
12211286 self . width ,
12221287 self . height ,
12231288 num_channels,
12241289 self . top_down ,
12251290 |row| {
1226- for pixel in row. chunks_mut ( num_channels) {
1227- let data = u32:: from ( reader. read_u16 :: < LittleEndian > ( ) ?) ;
1291+ reader. read_exact ( & mut row_buffer) ?;
1292+
1293+ for ( row_data, pixel) in row_buffer
1294+ . chunks_exact ( 2 )
1295+ . zip ( row. chunks_exact_mut ( num_channels) )
1296+ {
1297+ let data = u32:: from ( u16:: from_le_bytes ( row_data. try_into ( ) . unwrap ( ) ) ) ;
12281298
12291299 pixel[ 0 ] = bitfields. r . read ( data) ;
12301300 pixel[ 1 ] = bitfields. g . read ( data) ;
@@ -1237,7 +1307,7 @@ impl<R: BufRead + Seek> BmpDecoder<R> {
12371307 }
12381308 }
12391309 }
1240- reader . read_exact ( row_padding )
1310+ Ok ( ( ) )
12411311 } ,
12421312 ) ?;
12431313
@@ -1253,15 +1323,25 @@ impl<R: BufRead + Seek> BmpDecoder<R> {
12531323 let reader = & mut self . reader ;
12541324 reader. seek ( SeekFrom :: Start ( self . data_offset ) ) ?;
12551325
1326+ // Calculate row size in bytes (4 bytes per pixel, no padding for 32-bit)
1327+ let row_data_len = self . width as usize * 4 ;
1328+
1329+ let mut row_buffer = allocate_row_buffer ( row_data_len) ?;
1330+
12561331 with_rows (
12571332 buf,
12581333 self . width ,
12591334 self . height ,
12601335 num_channels,
12611336 self . top_down ,
12621337 |row| {
1263- for pixel in row. chunks_mut ( num_channels) {
1264- let data = reader. read_u32 :: < LittleEndian > ( ) ?;
1338+ reader. read_exact ( & mut row_buffer) ?;
1339+
1340+ for ( row_data, pixel) in row_buffer
1341+ . chunks_exact ( 4 )
1342+ . zip ( row. chunks_exact_mut ( num_channels) )
1343+ {
1344+ let data = u32:: from_le_bytes ( row_data. try_into ( ) . unwrap ( ) ) ;
12651345
12661346 pixel[ 0 ] = bitfields. r . read ( data) ;
12671347 pixel[ 1 ] = bitfields. g . read ( data) ;
@@ -1288,46 +1368,55 @@ impl<R: BufRead + Seek> BmpDecoder<R> {
12881368 format : & FormatFullBytes ,
12891369 ) -> ImageResult < ( ) > {
12901370 let num_channels = self . num_channels ( ) ;
1371+ let row_data_len = match * format {
1372+ FormatFullBytes :: RGB24 => self . width as usize * 3 ,
1373+ FormatFullBytes :: Format888 => self . width as usize * 4 ,
1374+ FormatFullBytes :: RGB32 | FormatFullBytes :: RGBA32 => self . width as usize * 4 ,
1375+ } ;
12911376 let row_padding_len = match * format {
1292- FormatFullBytes :: RGB24 => calculate_row_padding ( self . width as usize * 3 ) ,
1377+ FormatFullBytes :: RGB24 => calculate_row_padding ( row_data_len ) ,
12931378 _ => 0 ,
12941379 } ;
1295- let row_padding = & mut [ 0 ; 4 ] [ .. row_padding_len] ;
1380+ let total_row_len = row_data_len + row_padding_len;
12961381
12971382 self . reader . seek ( SeekFrom :: Start ( self . data_offset ) ) ?;
12981383
12991384 let reader = & mut self . reader ;
13001385
1386+ let mut row_buffer = allocate_row_buffer ( total_row_len) ?;
1387+
13011388 with_rows (
13021389 buf,
13031390 self . width ,
13041391 self . height ,
13051392 num_channels,
13061393 self . top_down ,
13071394 |row| {
1308- for pixel in row. chunks_mut ( num_channels) {
1309- if * format == FormatFullBytes :: Format888 {
1310- reader. read_u8 ( ) ?;
1311- }
1395+ reader. read_exact ( & mut row_buffer) ?;
13121396
1313- // Read the colour values (b, g, r).
1314- // Reading 3 bytes and reversing them is significantly faster than reading one
1315- // at a time.
1316- reader. read_exact ( & mut pixel[ 0 ..3 ] ) ?;
1317- pixel[ 0 ..3 ] . reverse ( ) ;
1397+ for ( i, pixel) in row. chunks_mut ( num_channels) . enumerate ( ) {
1398+ let offset = match * format {
1399+ FormatFullBytes :: Format888 => i * 4 + 1 , // Skip first byte
1400+ _ => {
1401+ i * match * format {
1402+ FormatFullBytes :: RGB24 => 3 ,
1403+ _ => 4 ,
1404+ }
1405+ }
1406+ } ;
13181407
1319- if * format == FormatFullBytes :: RGB32 {
1320- reader . read_u8 ( ) ? ;
1321- }
1408+ // Read the colour values (b, g, r) and reverse to (r, g, b)
1409+ pixel [ 0 .. 3 ] . copy_from_slice ( & row_buffer [ offset..offset + 3 ] ) ;
1410+ pixel [ 0 .. 3 ] . reverse ( ) ;
13221411
13231412 // Read the alpha channel if present
13241413 if * format == FormatFullBytes :: RGBA32 {
1325- reader . read_exact ( & mut pixel[ 3 .. 4 ] ) ? ;
1414+ pixel[ 3 ] = row_buffer [ offset + 3 ] ;
13261415 } else if num_channels == 4 {
13271416 pixel[ 3 ] = ALPHA_OPAQUE ;
13281417 }
13291418 }
1330- reader . read_exact ( row_padding )
1419+ Ok ( ( ) )
13311420 } ,
13321421 ) ?;
13331422
@@ -1347,23 +1436,30 @@ impl<R: BufRead + Seek> BmpDecoder<R> {
13471436 // two rows.
13481437 let mut row_iter = self . rows ( buf) ;
13491438
1439+ // Wrap reader in buffered RLE reader for efficient byte-by-byte access
1440+ let mut rle_reader = RleReader :: new ( & mut self . reader ) ;
1441+
1442+ // Pre-allocate buffer for RLE absolute mode (max 256 bytes)
1443+ let mut rle_indices_buffer = [ 0u8 ; 256 ] ;
1444+
13501445 while let Some ( row) = row_iter. next ( ) {
13511446 let mut pixel_iter = row. chunks_exact_mut ( num_channels) ;
13521447
13531448 let mut x = 0 ;
13541449 loop {
13551450 let instruction = {
1356- let control_byte = self . reader . read_u8 ( ) ?;
1451+ let control_byte = rle_reader. read_byte ( ) ?;
1452+
13571453 match control_byte {
13581454 RLE_ESCAPE => {
1359- let op = self . reader . read_u8 ( ) ?;
1455+ let op = rle_reader . read_byte ( ) ?;
13601456
13611457 match op {
13621458 RLE_ESCAPE_EOL => RLEInsn :: EndOfRow ,
13631459 RLE_ESCAPE_EOF => RLEInsn :: EndOfFile ,
13641460 RLE_ESCAPE_DELTA => {
1365- let xdelta = self . reader . read_u8 ( ) ?;
1366- let ydelta = self . reader . read_u8 ( ) ?;
1461+ let xdelta = rle_reader . read_byte ( ) ?;
1462+ let ydelta = rle_reader . read_byte ( ) ?;
13671463 RLEInsn :: Delta ( xdelta, ydelta)
13681464 }
13691465 _ => {
@@ -1372,14 +1468,13 @@ impl<R: BufRead + Seek> BmpDecoder<R> {
13721468 length = length. div_ceil ( 2 ) ;
13731469 }
13741470 length += length & 1 ;
1375- let mut buffer = Vec :: new ( ) ;
1376- self . reader . read_exact_vec ( & mut buffer, length) ?;
1377- RLEInsn :: Absolute ( op, buffer)
1471+ rle_reader. read_exact ( & mut rle_indices_buffer[ ..length] ) ?;
1472+ RLEInsn :: Absolute ( op, & rle_indices_buffer[ ..length] )
13781473 }
13791474 }
13801475 }
13811476 _ => {
1382- let palette_index = self . reader . read_u8 ( ) ?;
1477+ let palette_index = rle_reader . read_byte ( ) ?;
13831478 RLEInsn :: PixelRun ( control_byte, palette_index)
13841479 }
13851480 }
0 commit comments