Rewrite _to_buffer variants
We previously handed it a wrapper that was supposedly type-safe but really internally cast the buffer to bytes. That was rather pointless as the `_bytes` method could always be used instead. We replace the semantics by a utility which allocates an appropriate buffer with the internal limits, wrapping the exact sequence identified previously in the example as a pattern.
This commit is contained in:
1 parent
5150e91bbb
commit
5a3b11314e
2 files changed
+66
-29
No files matched your search
+1
-5
@@ -11,15 +11,11 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
let mut reader = Decoder::new(io)?;
|
let mut reader = Decoder::new(io)?;
|
||||||
|
|
||||||
let mut data = DecodingResult::I8(vec![]);
|
let mut data = DecodingResult::I8(vec![]);
|
||||||
let limits = tiff::decoder::Limits::unlimited();
|
|
||||||
|
|
||||||
for i in 0u32.. {
|
for i in 0u32.. {
|
||||||
let layout = reader.image_buffer_layout()?;
|
|
||||||
let colortype = reader.colortype()?;
|
let colortype = reader.colortype()?;
|
||||||
let dimensions = reader.dimensions()?;
|
let dimensions = reader.dimensions()?;
|
||||||
|
let layout = reader.read_image_to_buffer(&mut data)?;
|
||||||
data.resize_to(&layout, &limits)?;
|
|
||||||
reader.read_image_bytes(data.as_buffer(0).as_bytes_mut())?;
|
|
||||||
|
|
||||||
debug_planes(i, &mut data, &layout, &colortype, dimensions);
|
debug_planes(i, &mut data, &layout, &colortype, dimensions);
|
||||||
|
|
||||||
|
|||||||
+65
-24
@@ -60,7 +60,20 @@ impl DecodingResult {
|
|||||||
buffer: &BufferLayoutPreference,
|
buffer: &BufferLayoutPreference,
|
||||||
limits: &Limits,
|
limits: &Limits,
|
||||||
) -> Result<(), TiffError> {
|
) -> Result<(), TiffError> {
|
||||||
let extent = DecodingExtent::U8(buffer.complete_len);
|
let sample_type = buffer.sample_type.ok_or(TiffError::UnsupportedError(
|
||||||
|
TiffUnsupportedError::UnknownInterpretation,
|
||||||
|
))?;
|
||||||
|
|
||||||
|
let extent = sample_type.extent_for_bytes(buffer.complete_len);
|
||||||
|
self.resize_to_extent(extent, limits)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resize_to_extent(
|
||||||
|
&mut self,
|
||||||
|
extent: DecodingExtent,
|
||||||
|
limits: &Limits,
|
||||||
|
) -> Result<(), TiffError> {
|
||||||
|
// FIXME: we *can* reuse the allocation sometimes.
|
||||||
*self = extent.to_result_buffer(limits)?;
|
*self = extent.to_result_buffer(limits)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -1144,22 +1157,6 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
Ok(u32::try_from(self.image().chunk_offsets.len())?)
|
Ok(u32::try_from(self.image().chunk_offsets.len())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_chunk_to_buffer(
|
|
||||||
&mut self,
|
|
||||||
mut buffer: DecodingBuffer,
|
|
||||||
chunk_index: u32,
|
|
||||||
output_width: usize,
|
|
||||||
) -> TiffResult<()> {
|
|
||||||
let (width, height) = self.image().chunk_data_dimensions(chunk_index)?;
|
|
||||||
|
|
||||||
let mut layout = self.image().readout_for_size(width, height)?;
|
|
||||||
layout.set_row_stride(output_width)?;
|
|
||||||
|
|
||||||
self.read_chunk_to_bytes(buffer.as_bytes_mut(), chunk_index, &layout)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_chunk_to_bytes(
|
fn read_chunk_to_bytes(
|
||||||
&mut self,
|
&mut self,
|
||||||
buffer: &mut [u8],
|
buffer: &mut [u8],
|
||||||
@@ -1276,6 +1273,32 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Read the specified chunk (at index `chunk_index`) into a provide buffer.
|
||||||
|
///
|
||||||
|
/// It will re-allocate the buffer into the correct type and size, within the decoder's
|
||||||
|
/// configured limits, and then pass it to the underlying method. This is essentially a
|
||||||
|
/// type-safe wrapper around the raw [`Self::read_chunk_to_bytes`] method.
|
||||||
|
///
|
||||||
|
/// Note that for planar images each chunk contains only one sample of the underlying data.
|
||||||
|
pub fn read_chunk_to_buffer(
|
||||||
|
&mut self,
|
||||||
|
buffer: &mut DecodingResult,
|
||||||
|
chunk_index: u32,
|
||||||
|
output_width: usize,
|
||||||
|
) -> TiffResult<()> {
|
||||||
|
let (width, height) = self.image().chunk_data_dimensions(chunk_index)?;
|
||||||
|
|
||||||
|
let mut layout = self.image().readout_for_size(width, height)?;
|
||||||
|
layout.set_row_stride(output_width)?;
|
||||||
|
|
||||||
|
let extent = layout.result_extent_for_planes(0..1)?;
|
||||||
|
buffer.resize_to_extent(extent, &self.value_reader.limits)?;
|
||||||
|
|
||||||
|
self.read_chunk_to_bytes(buffer.as_buffer(0).as_bytes_mut(), chunk_index, &layout)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Read chunks corresponding to several planes of a region of pixels.
|
/// Read chunks corresponding to several planes of a region of pixels.
|
||||||
///
|
///
|
||||||
/// For non planar images this is equivalent to [`Self::read_chunk_bytes`] as there is only one
|
/// For non planar images this is equivalent to [`Self::read_chunk_bytes`] as there is only one
|
||||||
@@ -1388,9 +1411,9 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
|
|
||||||
/// Decodes the entire image into a provided buffer.
|
/// Decodes the entire image into a provided buffer.
|
||||||
///
|
///
|
||||||
/// Returns a [`TiffError::UsageError`] if the chunk is smaller than the size indicated with a
|
/// It will re-allocate the buffer into the correct type and size, within the decoder's
|
||||||
/// call to [`Self::image_buffer_layout`]. Note that the alignment may be arbitrary, but an
|
/// configured limits, and then pass it to the underlying method. This is essentially a
|
||||||
/// alignment smaller than the preferred alignment may perform worse.
|
/// type-safe wrapper around the raw [`Self::read_image_bytes`] method.
|
||||||
///
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
@@ -1398,19 +1421,37 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
/// use tiff::decoder::{Decoder, DecodingResult, Limits};
|
/// use tiff::decoder::{Decoder, DecodingResult, Limits};
|
||||||
///
|
///
|
||||||
/// let mut result = DecodingResult::I8(vec![]);
|
/// let mut result = DecodingResult::I8(vec![]);
|
||||||
/// let limits = Limits::unlimited();
|
|
||||||
///
|
///
|
||||||
/// let mut reader = /* */
|
/// let mut reader = /* */
|
||||||
/// # Decoder::new(std::io::Cursor::new(include_bytes!(concat!(
|
/// # Decoder::new(std::io::Cursor::new(include_bytes!(concat!(
|
||||||
/// # env!("CARGO_MANIFEST_DIR"), "/tests/images/tiled-gray-i1.tif"
|
/// # env!("CARGO_MANIFEST_DIR"), "/tests/images/tiled-gray-i1.tif"
|
||||||
/// # )))).unwrap();
|
/// # )))).unwrap();
|
||||||
///
|
///
|
||||||
/// let layout = reader.image_buffer_layout()?;
|
/// reader.read_image_to_buffer(&mut result)?;
|
||||||
/// result.resize_to(&layout, &limits)?;
|
|
||||||
/// reader.read_image_bytes(result.as_buffer(0).as_bytes_mut())?;
|
|
||||||
///
|
///
|
||||||
/// # Ok::<_, tiff::TiffError>(())
|
/// # Ok::<_, tiff::TiffError>(())
|
||||||
/// ```
|
/// ```
|
||||||
|
pub fn read_image_to_buffer(
|
||||||
|
&mut self,
|
||||||
|
result: &mut DecodingResult,
|
||||||
|
) -> TiffResult<BufferLayoutPreference> {
|
||||||
|
let readout = self.image().readout_for_image()?;
|
||||||
|
|
||||||
|
let planes = readout.to_plane_layout()?;
|
||||||
|
let layout = BufferLayoutPreference::from_planes(&planes);
|
||||||
|
|
||||||
|
let extent = readout.result_extent_for_planes(0..1)?;
|
||||||
|
result.resize_to_extent(extent, &self.value_reader.limits)?;
|
||||||
|
self.read_image_bytes(result.as_buffer(0).as_bytes_mut())?;
|
||||||
|
|
||||||
|
Ok(layout)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Decodes the entire image into a provided buffer.
|
||||||
|
///
|
||||||
|
/// Returns a [`TiffError::UsageError`] if the chunk is smaller than the size indicated with a
|
||||||
|
/// call to [`Self::image_buffer_layout`]. Note that the alignment may be arbitrary, but an
|
||||||
|
/// alignment smaller than the preferred alignment may perform worse.
|
||||||
///
|
///
|
||||||
/// # Error
|
/// # Error
|
||||||
///
|
///
|
||||||
|
|||||||
Reference in new issue
Block a user