Add method to retrieve planes of a tile

This is well-defined even if we add sub-sampling support later on. We
can adjust the layout type accordingly with factors per each plane. Note
that the layout, in theory, does not depend on the index of the unit if
we describe all planes for a multi-planar layout. The specification
requires that the subsampling factors divide the tile sizes. However we
have to handle non-planar images here and this leaves us open to other
potential parameters.
This commit is contained in:
A. Molzer committed 2025-12-28 15:06:10 +01:00
1 parent 5b9dc30919
commit 1f02ff8ca1
4 files changed
+181 -26

No files matched your search

+39 -10
View File
@@ -123,16 +123,6 @@ pub(crate) struct ReadoutLayout {
pub chunks_per_plane: u32,
}
/// A `ReadoutLayout` with pre-calculated plane information.
pub(crate) struct PlaneLayout {
/// The underlying readout layout.
pub readout: ReadoutLayout,
/// Buffer offset from one plane of output to the next.
pub plane_offsets: Vec<usize>,
/// Total number of bytes for all planes in given order.
pub total_bytes: usize,
}
impl Image {
pub fn from_reader<R: Read + Seek>(
decoder: &mut ValueReader<R>,
@@ -1032,3 +1022,42 @@ impl ReadoutLayout {
})
}
}
/// A `ReadoutLayout` with pre-calculated plane information.
pub(crate) struct PlaneLayout {
/// The underlying readout layout.
pub readout: ReadoutLayout,
/// Buffer offset from one plane of output to the next.
pub plane_offsets: Vec<usize>,
/// Total number of bytes for all planes in given order.
pub total_bytes: usize,
}
impl PlaneLayout {
/// Return the number of planes to extract into the provided buffer.
pub(crate) fn used_planes(&self, buffer: &[impl Sized]) -> TiffResult<u16> {
self.readout.assert_min_layout(buffer)?;
let buffer_len = core::mem::size_of_val(buffer);
// Note: with differently sized planes this is dependent on the plane.
let last_plane_start = buffer_len.checked_sub(self.readout.plane_stride);
// Find how many planes fit into the output buffer.
let used_plane_offsets = self
.plane_offsets
.iter()
.enumerate()
// Find the first plane that would not fit completely at its offset.
.skip_while(|(_, &offset)| last_plane_start >= Some(offset))
.nth(0)
// If all planes fit, use all of them.
.map_or(self.plane_offsets.len(), |(idx, _)| idx);
debug_assert!(
used_plane_offsets <= usize::from(u16::MAX),
"Planes limited by number of samples, which is encoded as u16"
);
Ok(used_plane_offsets as u16)
}
}