Merge TagReader and exposed IfdReader internals
Having the value reader itself take care of the bigtiff and limit semantics is a little cleaner, with the TagReader being responsible for the interface of grabbing specific types of IFD values.
This commit is contained in:
1 parent
f021e3e599
commit
e62cdfbf42
3 files changed
+42
-53
No files matched your search
+2
-13
@@ -82,21 +82,10 @@ pub(crate) struct Image {
|
|||||||
|
|
||||||
impl Image {
|
impl Image {
|
||||||
pub fn from_reader<R: Read + Seek>(
|
pub fn from_reader<R: Read + Seek>(
|
||||||
reader: &mut ValueReader<R>,
|
decoder: &mut ValueReader<R>,
|
||||||
ifd: Directory,
|
ifd: Directory,
|
||||||
) -> TiffResult<Image> {
|
) -> TiffResult<Image> {
|
||||||
let ValueReader {
|
let mut tag_reader = TagReader { decoder, ifd: &ifd };
|
||||||
reader,
|
|
||||||
bigtiff,
|
|
||||||
limits,
|
|
||||||
} = reader;
|
|
||||||
|
|
||||||
let mut tag_reader = TagReader {
|
|
||||||
reader,
|
|
||||||
limits,
|
|
||||||
ifd: &ifd,
|
|
||||||
bigtiff: *bigtiff,
|
|
||||||
};
|
|
||||||
|
|
||||||
let width = tag_reader.require_tag(Tag::ImageWidth)?.into_u32()?;
|
let width = tag_reader.require_tag(Tag::ImageWidth)?.into_u32()?;
|
||||||
let height = tag_reader.require_tag(Tag::ImageLength)?.into_u32()?;
|
let height = tag_reader.require_tag(Tag::ImageLength)?.into_u32()?;
|
||||||
|
|||||||
+13
-26
@@ -10,7 +10,6 @@ use crate::{
|
|||||||
UsageError,
|
UsageError,
|
||||||
};
|
};
|
||||||
use half::f16;
|
use half::f16;
|
||||||
use ifd::Entry;
|
|
||||||
|
|
||||||
use self::image::Image;
|
use self::image::Image;
|
||||||
use self::stream::{ByteOrder, EndianReader};
|
use self::stream::{ByteOrder, EndianReader};
|
||||||
@@ -286,8 +285,7 @@ struct ValueReader<R> {
|
|||||||
|
|
||||||
/// Reads a directory's tag values from an underlying stream.
|
/// Reads a directory's tag values from an underlying stream.
|
||||||
pub struct IfdDecoder<'lt> {
|
pub struct IfdDecoder<'lt> {
|
||||||
decoder: &'lt mut dyn EntryDecoder,
|
inner: tag_reader::TagReader<'lt, dyn tag_reader::EntryDecoder + 'lt>,
|
||||||
ifd: &'lt Directory,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rev_hpredict_nsamp(buf: &mut [u8], bit_depth: u8, samples: usize) {
|
fn rev_hpredict_nsamp(buf: &mut [u8], bit_depth: u8, samples: usize) {
|
||||||
@@ -987,8 +985,10 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
/// Get the IFD decoder for our current image IFD.
|
/// Get the IFD decoder for our current image IFD.
|
||||||
fn image_ifd(&mut self) -> IfdDecoder<'_> {
|
fn image_ifd(&mut self) -> IfdDecoder<'_> {
|
||||||
IfdDecoder {
|
IfdDecoder {
|
||||||
decoder: &mut self.value_reader,
|
inner: tag_reader::TagReader {
|
||||||
ifd: self.image.ifd.as_ref().unwrap(),
|
decoder: &mut self.value_reader,
|
||||||
|
ifd: self.image.ifd.as_ref().unwrap(),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1018,8 +1018,10 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
/// ```
|
/// ```
|
||||||
pub fn read_directory_tags<'ifd>(&'ifd mut self, ifd: &'ifd Directory) -> IfdDecoder<'ifd> {
|
pub fn read_directory_tags<'ifd>(&'ifd mut self, ifd: &'ifd Directory) -> IfdDecoder<'ifd> {
|
||||||
IfdDecoder {
|
IfdDecoder {
|
||||||
decoder: &mut self.value_reader,
|
inner: tag_reader::TagReader {
|
||||||
ifd,
|
decoder: &mut self.value_reader,
|
||||||
|
ifd,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1184,27 +1186,11 @@ impl<R: Seek + Read> ValueReader<R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
trait EntryDecoder {
|
|
||||||
/// Turn an entry into a value by fetching the required bytes in the stream.
|
|
||||||
fn entry_val(&mut self, entry: &Entry) -> TiffResult<ifd::Value>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R: Seek + Read> EntryDecoder for ValueReader<R> {
|
|
||||||
fn entry_val(&mut self, entry: &Entry) -> TiffResult<ifd::Value> {
|
|
||||||
entry.val(&self.limits, self.bigtiff, &mut self.reader)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IfdDecoder<'_> {
|
impl IfdDecoder<'_> {
|
||||||
/// Tries to retrieve a tag.
|
/// Tries to retrieve a tag.
|
||||||
/// Return `Ok(None)` if the tag is not present.
|
/// Return `Ok(None)` if the tag is not present.
|
||||||
pub fn find_tag(&mut self, tag: Tag) -> TiffResult<Option<ifd::Value>> {
|
pub fn find_tag(&mut self, tag: Tag) -> TiffResult<Option<ifd::Value>> {
|
||||||
let entry = match self.ifd.get(tag) {
|
self.inner.find_tag(tag)
|
||||||
None => return Ok(None),
|
|
||||||
Some(entry) => entry.clone(),
|
|
||||||
};
|
|
||||||
|
|
||||||
self.decoder.entry_val(&entry).map(Some)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to retrieve a tag and convert it to the desired unsigned type.
|
/// Tries to retrieve a tag and convert it to the desired unsigned type.
|
||||||
@@ -1311,9 +1297,10 @@ impl IfdDecoder<'_> {
|
|||||||
impl<'l> IfdDecoder<'l> {
|
impl<'l> IfdDecoder<'l> {
|
||||||
/// Returns an iterator over all tags in the current image, along with their values.
|
/// Returns an iterator over all tags in the current image, along with their values.
|
||||||
pub fn tag_iter(self) -> impl Iterator<Item = TiffResult<(Tag, ifd::Value)>> + 'l {
|
pub fn tag_iter(self) -> impl Iterator<Item = TiffResult<(Tag, ifd::Value)>> + 'l {
|
||||||
self.ifd
|
self.inner
|
||||||
|
.ifd
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(tag, entry)| match self.decoder.entry_val(entry) {
|
.map(|(tag, entry)| match self.inner.decoder.entry_val(entry) {
|
||||||
Ok(value) => Ok((tag, value)),
|
Ok(value) => Ok((tag, value)),
|
||||||
Err(err) => Err(err),
|
Err(err) => Err(err),
|
||||||
})
|
})
|
||||||
|
|||||||
+27
-14
@@ -3,23 +3,35 @@ use std::io::{Read, Seek};
|
|||||||
use crate::{tags::Tag, Directory};
|
use crate::{tags::Tag, Directory};
|
||||||
use crate::{TiffError, TiffFormatError, TiffResult};
|
use crate::{TiffError, TiffFormatError, TiffResult};
|
||||||
|
|
||||||
use super::ifd::Value;
|
use super::ifd::{Entry, Value};
|
||||||
use super::stream::EndianReader;
|
use super::ValueReader;
|
||||||
use super::Limits;
|
|
||||||
|
|
||||||
pub(crate) struct TagReader<'a, R: Read + Seek> {
|
pub(crate) struct TagReader<'lt, R: EntryDecoder + ?Sized> {
|
||||||
pub reader: &'a mut EndianReader<R>,
|
pub(crate) decoder: &'lt mut R,
|
||||||
pub ifd: &'a Directory,
|
pub(crate) ifd: &'lt Directory,
|
||||||
pub limits: &'a Limits,
|
|
||||||
pub bigtiff: bool,
|
|
||||||
}
|
}
|
||||||
impl<'a, R: Read + Seek> TagReader<'a, R> {
|
|
||||||
pub(crate) fn find_tag(&mut self, tag: Tag) -> TiffResult<Option<Value>> {
|
pub(crate) trait EntryDecoder {
|
||||||
Ok(match self.ifd.get(tag) {
|
/// Turn an entry into a value by fetching the required bytes in the stream.
|
||||||
Some(entry) => Some(entry.clone().val(self.limits, self.bigtiff, self.reader)?),
|
fn entry_val(&mut self, entry: &Entry) -> TiffResult<Value>;
|
||||||
None => None,
|
}
|
||||||
})
|
|
||||||
|
impl<R: Seek + Read> EntryDecoder for ValueReader<R> {
|
||||||
|
fn entry_val(&mut self, entry: &Entry) -> TiffResult<Value> {
|
||||||
|
entry.val(&self.limits, self.bigtiff, &mut self.reader)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, R: EntryDecoder + ?Sized> TagReader<'a, R> {
|
||||||
|
pub(crate) fn find_tag(&mut self, tag: Tag) -> TiffResult<Option<Value>> {
|
||||||
|
let entry = match self.ifd.get(tag) {
|
||||||
|
None => return Ok(None),
|
||||||
|
Some(entry) => entry.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.decoder.entry_val(&entry).map(Some)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn require_tag(&mut self, tag: Tag) -> TiffResult<Value> {
|
pub(crate) fn require_tag(&mut self, tag: Tag) -> TiffResult<Value> {
|
||||||
match self.find_tag(tag)? {
|
match self.find_tag(tag)? {
|
||||||
Some(val) => Ok(val),
|
Some(val) => Ok(val),
|
||||||
@@ -28,6 +40,7 @@ impl<'a, R: Read + Seek> TagReader<'a, R> {
|
|||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn find_tag_uint_vec<T: TryFrom<u64>>(&mut self, tag: Tag) -> TiffResult<Option<Vec<T>>> {
|
pub fn find_tag_uint_vec<T: TryFrom<u64>>(&mut self, tag: Tag) -> TiffResult<Option<Vec<T>>> {
|
||||||
self.find_tag(tag)?
|
self.find_tag(tag)?
|
||||||
.map(|v| v.into_u64_vec())
|
.map(|v| v.into_u64_vec())
|
||||||
|
|||||||
Reference in new issue
Block a user