Add Reader::read_from_container.

This commit is contained in:
KAMADA Ken'ichi 2020-01-19 20:58:01 +09:00
parent 0e398cd63a
commit 5219996fa4
2 changed files with 47 additions and 1 deletions

View File

@ -42,7 +42,8 @@ fn main() {
fn dump_file(path: &Path) -> Result<(), exif::Error> {
let file = File::open(path)?;
let reader = exif::Reader::new(&mut BufReader::new(&file))?;
let reader = exif::Reader::read_from_container(
&mut BufReader::new(&file))?;
println!("{}", path.display());
for f in reader.fields() {

View File

@ -29,6 +29,7 @@ use std::io;
use std::io::Read;
use crate::error::Error;
use crate::isobmff;
use crate::jpeg;
use crate::tag::Tag;
use crate::tiff;
@ -101,6 +102,40 @@ impl Reader {
})
}
/// Reads an image file and parses the Exif attributes in it.
/// If an error occurred, `exif::Error` is returned.
///
/// Supported formats are HEIF, JPEG, and TIFF.
///
/// This method is provided for the convenience even though
/// parsing containers is basically out of the scope of this library.
pub fn read_from_container<R>(reader: &mut R) -> Result<Reader, Error>
where R: io::BufRead + io::Seek {
let mut buf = Vec::new();
reader.by_ref().take(4096).read_to_end(&mut buf)?;
if tiff::is_tiff(&buf) {
reader.read_to_end(&mut buf)?;
} else if jpeg::is_jpeg(&buf) {
buf = jpeg::get_exif_attr(&mut buf.chain(reader))?;
} else if isobmff::is_heif(&buf) {
reader.seek(io::SeekFrom::Start(0))?;
buf = isobmff::get_exif_attr(reader)?;
} else {
return Err(Error::InvalidFormat("Unknown image format"));
}
let (entries, le) = tiff::parse_exif(&buf)?;
let entry_map = entries.iter().enumerate()
.map(|(i, e)| (e.ifd_num_tag(), i)).collect();
Ok(Reader {
buf: buf,
entries: entries,
entry_map: entry_map,
little_endian: le,
})
}
/// Returns the slice that contains the TIFF data.
#[inline]
pub fn buf(&self) -> &[u8] {
@ -185,4 +220,14 @@ mod tests {
assert_eq!(gpslat.display_value().with_unit(&reader).to_string(),
"10 deg 0 min 0 sec [GPSLatitudeRef missing]");
}
#[test]
fn heif() {
let file = std::fs::File::open("tests/exif.heic").unwrap();
let reader = Reader::read_from_container(
&mut std::io::BufReader::new(&file)).unwrap();
assert_eq!(reader.fields().len(), 2);
let exifver = reader.get_field(Tag::ExifVersion, In::PRIMARY).unwrap();
assert_eq!(exifver.display_value().to_string(), "2.31");
}
}