diff --git a/CHANGELOG.md b/CHANGELOG.md index a630eb0..eb1dc01 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ - [#55](https://github.com/embedded-graphics/tinybmp/pull/55) Added methods `CompressionMethod::is_compressed` and `Header::bytes_per_row`. The latter is essential information when walking through the bytes yourself. +### Fixed + +- [#57](https://github.com/embedded-graphics/tinybmp/pull/57) Fixed RLE4/RLE8 compressed BMP pixel iterator returning only the first row of pixels instead of all pixels. + ## [0.7.0] - 2026-01-14 ### Fixed diff --git a/src/raw_iter.rs b/src/raw_iter.rs index 17d0389..dcddc4e 100644 --- a/src/raw_iter.rs +++ b/src/raw_iter.rs @@ -213,7 +213,7 @@ impl<'a> Rle8Colors<'a> { Rle8Colors { data: raw_bmp.image_data(), rle_state: RleState::Starting, - start_of_row: false, + start_of_row: true, } } @@ -252,6 +252,7 @@ impl<'a> Iterator for Rle8Colors<'a> { } else { self.data = self.data.get(1..)?; } + self.start_of_row = false; return Some(RawU8::from(value)); } RleState::Running { @@ -268,6 +269,7 @@ impl<'a> Iterator for Rle8Colors<'a> { is_odd, }; } + self.start_of_row = false; return Some(RawU8::from(value)); } RleState::Starting => { @@ -284,9 +286,8 @@ impl<'a> Iterator for Rle8Colors<'a> { // the pair, which can be one of the following values. match param { 0 => { - if !self.start_of_row { - return None; - } + // End of line - move to next row + self.start_of_row = true; } 1 => { // End of bitmap @@ -340,7 +341,7 @@ impl<'a> Rle4Colors<'a> { Rle4Colors { data: raw_bmp.image_data(), rle_state: RleState::Starting, - start_of_row: false, + start_of_row: true, } } @@ -400,6 +401,7 @@ impl<'a> Iterator for Rle4Colors<'a> { // remove the padding byte too self.data = self.data.get(1..)?; } + self.start_of_row = false; return Some(RawU4::from(nibble_value)); } RleState::Running { @@ -434,6 +436,7 @@ impl<'a> Iterator for Rle4Colors<'a> { }; } + self.start_of_row = false; return Some(RawU4::from(nibble_value)); } RleState::Starting => { @@ -450,9 +453,8 @@ impl<'a> Iterator for Rle4Colors<'a> { // the pair, which can be one of the following values. match param { 0 => { - if !self.start_of_row { - return None; - } + // End of line - move to next row + self.start_of_row = true; } 1 => { // End of bitmap diff --git a/tests/logo.rs b/tests/logo.rs index b748cce..d3d877c 100644 --- a/tests/logo.rs +++ b/tests/logo.rs @@ -139,6 +139,12 @@ fn logo_indexed_1bpp_pixel_getter() { bmp.assert_eq(&raw); } +#[test] +fn logo_indexed_1bpp_pixel_iteration() { + let bmp: Bmp<'_, Bgr888> = Bmp::from_slice(include_bytes!("logo-indexed-1bpp.bmp")).unwrap(); + assert_eq!(bmp.pixels().count(), WIDTH * HEIGHT); +} + #[test] fn logo_indexed_4bpp() { let raw = draw_raw::(include_bytes!("logo-indexed-4bpp.raw")); @@ -147,6 +153,12 @@ fn logo_indexed_4bpp() { bmp.assert_eq(&raw); } +#[test] +fn logo_indexed_4bpp_pixel_iteration() { + let bmp: Bmp<'_, Bgr888> = Bmp::from_slice(include_bytes!("logo-indexed-4bpp.bmp")).unwrap(); + assert_eq!(bmp.pixels().count(), WIDTH * HEIGHT); +} + #[test] fn logo_indexed_4bpp_rle4() { let raw = draw_raw::(include_bytes!("logo-indexed-4bpp.raw")); @@ -155,6 +167,13 @@ fn logo_indexed_4bpp_rle4() { bmp.assert_eq(&raw); } +#[test] +fn logo_indexed_4bpp_rle4_pixel_iteration() { + let bmp: Bmp<'_, Bgr888> = + Bmp::from_slice(include_bytes!("logo-indexed-4bpp-rle4.bmp")).unwrap(); + assert_eq!(bmp.pixels().count(), WIDTH * HEIGHT); +} + #[test] fn logo_indexed_4bpp_pixel_getter() { let raw = draw_raw::(include_bytes!("logo-indexed-4bpp.raw")); @@ -179,6 +198,12 @@ fn logo_indexed_8bpp_pixel_getter() { bmp.assert_eq(&raw); } +#[test] +fn logo_indexed_8bpp_pixel_iteration() { + let bmp: Bmp<'_, Bgr888> = Bmp::from_slice(include_bytes!("logo-indexed-8bpp.bmp")).unwrap(); + assert_eq!(bmp.pixels().count(), WIDTH * HEIGHT); +} + #[test] fn logo_indexed_8bpp_rle8() { let raw = draw_raw::(include_bytes!("logo-indexed-8bpp.raw")); @@ -187,6 +212,13 @@ fn logo_indexed_8bpp_rle8() { bmp.assert_eq(&raw); } +#[test] +fn logo_indexed_8bpp_rle8_pixel_iteration() { + let bmp: Bmp<'_, Bgr888> = + Bmp::from_slice(include_bytes!("logo-indexed-8bpp-rle8.bmp")).unwrap(); + assert_eq!(bmp.pixels().count(), WIDTH * HEIGHT); +} + #[test] fn logo_rgb555() { let raw = draw_raw::(include_bytes!("logo-rgb555.raw")); @@ -203,6 +235,12 @@ fn logo_rgb555_pixel_getter() { bmp.assert_eq(&raw); } +#[test] +fn logo_rgb555_pixel_iteration() { + let bmp: Bmp<'_, Rgb555> = Bmp::from_slice(include_bytes!("logo-rgb555.bmp")).unwrap(); + assert_eq!(bmp.pixels().count(), WIDTH * HEIGHT); +} + #[test] fn logo_rgb565() { let raw = draw_raw::(include_bytes!("logo-rgb565.raw")); @@ -219,6 +257,12 @@ fn logo_rgb565_pixel_getter() { bmp.assert_eq(&raw); } +#[test] +fn logo_rgb565_pixel_iteration() { + let bmp: Bmp<'_, Rgb565> = Bmp::from_slice(include_bytes!("logo-rgb565.bmp")).unwrap(); + assert_eq!(bmp.pixels().count(), WIDTH * HEIGHT); +} + #[test] fn logo_rgb888_24bpp() { let raw = draw_raw::(include_bytes!("logo-rgb888.raw")); @@ -235,6 +279,12 @@ fn logo_rgb888_24bpp_pixel_getter() { bmp.assert_eq(&raw); } +#[test] +fn logo_rgb888_24bpp_pixel_iteration() { + let bmp: Bmp<'_, Bgr888> = Bmp::from_slice(include_bytes!("logo-rgb888-24bpp.bmp")).unwrap(); + assert_eq!(bmp.pixels().count(), WIDTH * HEIGHT); +} + #[test] fn logo_rgb888_32bpp() { let raw = draw_raw::(include_bytes!("logo-rgb888.raw")); @@ -250,3 +300,9 @@ fn logo_rgb888_32bpp_pixel_getter() { bmp.assert_eq(&raw); } + +#[test] +fn logo_rgb888_32bpp_pixel_iteration() { + let bmp: Bmp<'_, Bgr888> = Bmp::from_slice(include_bytes!("logo-rgb888-32bpp.bmp")).unwrap(); + assert_eq!(bmp.pixels().count(), WIDTH * HEIGHT); +}