| 1 | use super::stream::{DecodingError, FormatErrorInner}; |
| 2 | use crate::common::BytesPerPixel; |
| 3 | use crate::filter::{unfilter, FilterType}; |
| 4 | |
| 5 | // Buffer for temporarily holding decompressed, not-yet-`unfilter`-ed rows. |
| 6 | pub(crate) struct UnfilteringBuffer { |
| 7 | /// Vec containing the uncompressed image data currently being processed. |
| 8 | data_stream: Vec<u8>, |
| 9 | /// Index in `data_stream` where the previous row starts. |
| 10 | /// This excludes the filter type byte - it points at the first byte of actual pixel data. |
| 11 | /// The pixel data is already-`unfilter`-ed. |
| 12 | /// If `prev_start == current_start` then it means that there is no previous row. |
| 13 | prev_start: usize, |
| 14 | /// Index in `data_stream` where the current row starts. |
| 15 | /// This points at the filter type byte of the current row (i.e. the actual pixel data starts at `current_start + 1`) |
| 16 | /// The pixel data is not-yet-`unfilter`-ed. |
| 17 | current_start: usize, |
| 18 | } |
| 19 | |
| 20 | impl UnfilteringBuffer { |
| 21 | /// Asserts in debug builds that all the invariants hold. No-op in release |
| 22 | /// builds. Intended to be called after creating or mutating `self` to |
| 23 | /// ensure that the final state preserves the invariants. |
| 24 | fn debug_assert_invariants(&self) { |
| 25 | debug_assert!(self.prev_start <= self.current_start); |
| 26 | debug_assert!(self.prev_start <= self.data_stream.len()); |
| 27 | debug_assert!(self.current_start <= self.data_stream.len()); |
| 28 | } |
| 29 | |
| 30 | pub fn new() -> Self { |
| 31 | let result = Self { |
| 32 | data_stream: Vec::new(), |
| 33 | prev_start: 0, |
| 34 | current_start: 0, |
| 35 | }; |
| 36 | result.debug_assert_invariants(); |
| 37 | result |
| 38 | } |
| 39 | |
| 40 | /// Called to indicate that there is no previous row (e.g. when the current |
| 41 | /// row is the first scanline of a given Adam7 pass). |
| 42 | pub fn reset_prev_row(&mut self) { |
| 43 | self.prev_start = self.current_start; |
| 44 | self.debug_assert_invariants(); |
| 45 | } |
| 46 | |
| 47 | /// Returns the previous (already `unfilter`-ed) row. |
| 48 | pub fn prev_row(&self) -> &[u8] { |
| 49 | // No point calling this if there is no previous row. |
| 50 | debug_assert!(self.prev_start < self.current_start); |
| 51 | |
| 52 | &self.data_stream[self.prev_start..self.current_start] |
| 53 | } |
| 54 | |
| 55 | /// Returns how many bytes of the current row are present in the buffer. |
| 56 | pub fn curr_row_len(&self) -> usize { |
| 57 | self.data_stream.len() - self.current_start |
| 58 | } |
| 59 | |
| 60 | /// Returns a `&mut Vec<u8>` suitable for passing to |
| 61 | /// `ReadDecoder.decode_image_data` or `StreamingDecoder.update`. |
| 62 | /// |
| 63 | /// Invariants of `self` depend on the assumption that the caller will only |
| 64 | /// append new bytes to the returned vector (which is indeed the behavior of |
| 65 | /// `ReadDecoder` and `StreamingDecoder`). TODO: Consider protecting the |
| 66 | /// invariants by returning an append-only view of the vector |
| 67 | /// (`FnMut(&[u8])`??? or maybe `std::io::Write`???). |
| 68 | pub fn as_mut_vec(&mut self) -> &mut Vec<u8> { |
| 69 | // Opportunistically compact the current buffer by discarding bytes |
| 70 | // before `prev_start`. |
| 71 | if self.prev_start > 0 { |
| 72 | self.data_stream.copy_within(self.prev_start.., 0); |
| 73 | self.data_stream |
| 74 | .truncate(self.data_stream.len() - self.prev_start); |
| 75 | self.current_start -= self.prev_start; |
| 76 | self.prev_start = 0; |
| 77 | self.debug_assert_invariants(); |
| 78 | } |
| 79 | |
| 80 | &mut self.data_stream |
| 81 | } |
| 82 | |
| 83 | /// Runs `unfilter` on the current row, and then shifts rows so that the current row becomes the previous row. |
| 84 | /// |
| 85 | /// Will panic if `self.curr_row_len() < rowlen`. |
| 86 | pub fn unfilter_curr_row( |
| 87 | &mut self, |
| 88 | rowlen: usize, |
| 89 | bpp: BytesPerPixel, |
| 90 | ) -> Result<(), DecodingError> { |
| 91 | debug_assert!(rowlen >= 2); // 1 byte for `FilterType` and at least 1 byte of pixel data. |
| 92 | |
| 93 | let (prev, row) = self.data_stream.split_at_mut(self.current_start); |
| 94 | let prev: &[u8] = prev; // `prev` is immutable |
| 95 | let prev = &prev[self.prev_start..]; |
| 96 | debug_assert!(prev.is_empty() || prev.len() == (rowlen - 1)); |
| 97 | |
| 98 | // Get the filter type. |
| 99 | let filter = FilterType::from_u8(row[0]).ok_or(DecodingError::Format( |
| 100 | FormatErrorInner::UnknownFilterMethod(row[0]).into(), |
| 101 | ))?; |
| 102 | let row = &mut row[1..rowlen]; |
| 103 | |
| 104 | unfilter(filter, bpp, prev, row); |
| 105 | |
| 106 | self.prev_start = self.current_start + 1; |
| 107 | self.current_start += rowlen; |
| 108 | self.debug_assert_invariants(); |
| 109 | |
| 110 | Ok(()) |
| 111 | } |
| 112 | } |
| 113 | |