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 {
|
||||
pub fn from_reader<R: Read + Seek>(
|
||||
reader: &mut ValueReader<R>,
|
||||
decoder: &mut ValueReader<R>,
|
||||
ifd: Directory,
|
||||
) -> TiffResult<Image> {
|
||||
let ValueReader {
|
||||
reader,
|
||||
bigtiff,
|
||||
limits,
|
||||
} = reader;
|
||||
|
||||
let mut tag_reader = TagReader {
|
||||
reader,
|
||||
limits,
|
||||
ifd: &ifd,
|
||||
bigtiff: *bigtiff,
|
||||
};
|
||||
let mut tag_reader = TagReader { decoder, ifd: &ifd };
|
||||
|
||||
let width = tag_reader.require_tag(Tag::ImageWidth)?.into_u32()?;
|
||||
let height = tag_reader.require_tag(Tag::ImageLength)?.into_u32()?;
|
||||
|
||||
+13
-26
@@ -10,7 +10,6 @@ use crate::{
|
||||
UsageError,
|
||||
};
|
||||
use half::f16;
|
||||
use ifd::Entry;
|
||||
|
||||
use self::image::Image;
|
||||
use self::stream::{ByteOrder, EndianReader};
|
||||
@@ -286,8 +285,7 @@ struct ValueReader<R> {
|
||||
|
||||
/// Reads a directory's tag values from an underlying stream.
|
||||
pub struct IfdDecoder<'lt> {
|
||||
decoder: &'lt mut dyn EntryDecoder,
|
||||
ifd: &'lt Directory,
|
||||
inner: tag_reader::TagReader<'lt, dyn tag_reader::EntryDecoder + 'lt>,
|
||||
}
|
||||
|
||||
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.
|
||||
fn image_ifd(&mut self) -> IfdDecoder<'_> {
|
||||
IfdDecoder {
|
||||
decoder: &mut self.value_reader,
|
||||
ifd: self.image.ifd.as_ref().unwrap(),
|
||||
inner: tag_reader::TagReader {
|
||||
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> {
|
||||
IfdDecoder {
|
||||
decoder: &mut self.value_reader,
|
||||
ifd,
|
||||
inner: tag_reader::TagReader {
|
||||
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<'_> {
|
||||
/// Tries to retrieve a tag.
|
||||
/// Return `Ok(None)` if the tag is not present.
|
||||
pub fn find_tag(&mut self, tag: Tag) -> TiffResult<Option<ifd::Value>> {
|
||||
let entry = match self.ifd.get(tag) {
|
||||
None => return Ok(None),
|
||||
Some(entry) => entry.clone(),
|
||||
};
|
||||
|
||||
self.decoder.entry_val(&entry).map(Some)
|
||||
self.inner.find_tag(tag)
|
||||
}
|
||||
|
||||
/// Tries to retrieve a tag and convert it to the desired unsigned type.
|
||||
@@ -1311,9 +1297,10 @@ impl IfdDecoder<'_> {
|
||||
impl<'l> IfdDecoder<'l> {
|
||||
/// 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 {
|
||||
self.ifd
|
||||
self.inner
|
||||
.ifd
|
||||
.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)),
|
||||
Err(err) => Err(err),
|
||||
})
|
||||
|
||||
+27
-14
@@ -3,23 +3,35 @@ use std::io::{Read, Seek};
|
||||
use crate::{tags::Tag, Directory};
|
||||
use crate::{TiffError, TiffFormatError, TiffResult};
|
||||
|
||||
use super::ifd::Value;
|
||||
use super::stream::EndianReader;
|
||||
use super::Limits;
|
||||
use super::ifd::{Entry, Value};
|
||||
use super::ValueReader;
|
||||
|
||||
pub(crate) struct TagReader<'a, R: Read + Seek> {
|
||||
pub reader: &'a mut EndianReader<R>,
|
||||
pub ifd: &'a Directory,
|
||||
pub limits: &'a Limits,
|
||||
pub bigtiff: bool,
|
||||
pub(crate) struct TagReader<'lt, R: EntryDecoder + ?Sized> {
|
||||
pub(crate) decoder: &'lt mut R,
|
||||
pub(crate) ifd: &'lt Directory,
|
||||
}
|
||||
impl<'a, R: Read + Seek> TagReader<'a, R> {
|
||||
pub(crate) fn find_tag(&mut self, tag: Tag) -> TiffResult<Option<Value>> {
|
||||
Ok(match self.ifd.get(tag) {
|
||||
Some(entry) => Some(entry.clone().val(self.limits, self.bigtiff, self.reader)?),
|
||||
None => None,
|
||||
})
|
||||
|
||||
pub(crate) trait EntryDecoder {
|
||||
/// Turn an entry into a value by fetching the required bytes in the stream.
|
||||
fn entry_val(&mut self, entry: &Entry) -> TiffResult<Value>;
|
||||
}
|
||||
|
||||
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> {
|
||||
match self.find_tag(tag)? {
|
||||
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>>> {
|
||||
self.find_tag(tag)?
|
||||
.map(|v| v.into_u64_vec())
|
||||
|
||||
Reference in new issue
Block a user