diff --git a/src/decoder/image.rs b/src/decoder/image.rs index 2571b07..59046a9 100644 --- a/src/decoder/image.rs +++ b/src/decoder/image.rs @@ -30,10 +30,8 @@ pub(crate) struct TileAttributes { } pub(crate) struct PlaneLayout { - /// Buffer offset from one row of the image to its next, in bytes. - pub output_row_stride: usize, - /// Number of bytes in a plane. - pub plane_stride: usize, + /// The underlying readout layout. + pub readout: ReadoutLayout, /// Buffer offset from one plane of output to the next. pub plane_offsets: Vec, /// Total number of bytes for all planes in given order. @@ -99,6 +97,7 @@ pub(crate) struct Image { } /// Describes how to read a tile-aligned portion of the image. +#[derive(Clone)] pub(crate) struct ReadoutLayout { /// The planar configuration, which applies to both the underlying image and the output buffer. /// This may be relaxed if we find a clean enough way to provide it. @@ -1040,10 +1039,9 @@ impl ReadoutLayout { }; Ok(PlaneLayout { - output_row_stride: self.row_stride, - plane_stride: self.plane_stride, plane_offsets, total_bytes, + readout: self.clone(), }) } } diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 97edfbf..ae361ee 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -226,10 +226,10 @@ pub struct BufferLayoutPreference { impl BufferLayoutPreference { fn from_planes(layout: &image::PlaneLayout) -> Self { BufferLayoutPreference { - len: layout.plane_stride, - row_stride: core::num::NonZeroUsize::new(layout.output_row_stride), + len: layout.readout.plane_stride, + row_stride: core::num::NonZeroUsize::new(layout.readout.row_stride), planes: layout.plane_offsets.len(), - plane_stride: core::num::NonZeroUsize::new(layout.plane_stride), + plane_stride: core::num::NonZeroUsize::new(layout.readout.plane_stride), complete_len: layout.total_bytes, } } @@ -1299,22 +1299,24 @@ impl Decoder { let readout = self.image().readout_for_image()?; let ref layout @ image::PlaneLayout { - output_row_stride: _, - plane_stride, ref plane_offsets, // We assume that is correct, so really it can be ignored. total_bytes: _, + ref readout, } = readout.to_plane_layout()?; let preference = BufferLayoutPreference::from_planes(layout); preference.assert_min_layout(buffer)?; + // Note: with differently sized planes this is dependent on the plane. + let last_plane_start = buffer.len().checked_sub(readout.plane_stride); + // Find how many planes fit into the output buffer. let used_plane_offsets = plane_offsets .iter() .enumerate() // Find the first plane that would not fit completely at its offset. - .skip_while(|(_, &offset)| buffer.len().checked_sub(plane_stride) >= Some(offset)) + .skip_while(|(_, &offset)| last_plane_start >= Some(offset)) .nth(0) // If all planes fit, use all of them. .map_or(plane_offsets.len(), |(idx, _)| idx);