Add parse_image(), which accepts a JPEG or TIFF image.
This commit is contained in:
parent
e5ffcb23c4
commit
906a25cb31
|
@ -0,0 +1,59 @@
|
|||
//
|
||||
// Copyright (c) 2016 KAMADA Ken'ichi.
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
// 1. Redistributions of source code must retain the above copyright
|
||||
// notice, this list of conditions and the following disclaimer.
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
// OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
// OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
// SUCH DAMAGE.
|
||||
//
|
||||
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::mem;
|
||||
|
||||
use error::Error;
|
||||
use jpeg;
|
||||
use tiff;
|
||||
use tiff::Field;
|
||||
|
||||
/// Parse the Exif attributes in a JPEG or TIFF image data.
|
||||
///
|
||||
/// Returns a Vec of Exif fields and a bool.
|
||||
/// The boolean value is true if the data is little endian.
|
||||
/// If an error occurred, `exif::Error` is returned.
|
||||
///
|
||||
/// The `buf` must be an empty `Vec<u8>` when this function is called.
|
||||
/// The raw Exif data is read into it.
|
||||
pub fn parse_image<'a, R>(mut reader: &mut R, mut buf: &'a mut Vec<u8>)
|
||||
-> Result<(Vec<Field<'a>>, bool), Error>
|
||||
where R: io::BufRead
|
||||
{
|
||||
try!(reader.by_ref().take(4).read_to_end(buf));
|
||||
if jpeg::is_jpeg(buf) {
|
||||
let exif_buf = try!(jpeg::get_exif_attr(
|
||||
&mut buf.as_mut_slice().chain(reader)));
|
||||
mem::replace(buf, exif_buf);
|
||||
} else if tiff::is_tiff(buf) {
|
||||
try!(reader.read_to_end(&mut buf));
|
||||
} else {
|
||||
return Err(Error::InvalidFormat("Unknown image format"));
|
||||
}
|
||||
tiff::parse_exif(buf)
|
||||
}
|
|
@ -45,6 +45,9 @@ mod marker {
|
|||
pub const APP1: u8 = 0xe1;
|
||||
}
|
||||
|
||||
// SOI marker as the JPEG header.
|
||||
const JPEG_SIG: [u8; 2] = [marker::P, marker::SOI];
|
||||
|
||||
// Exif identifier code "Exif\0\0". [EXIF23 4.7.2]
|
||||
const EXIF_ID: [u8; 6] = [0x45, 0x78, 0x69, 0x66, 0x00, 0x00];
|
||||
|
||||
|
@ -99,6 +102,10 @@ fn get_exif_attr_sub<R>(reader: &mut R)
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_jpeg(buf: &[u8]) -> bool {
|
||||
buf.starts_with(&JPEG_SIG)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::io::Cursor;
|
||||
|
|
|
@ -28,19 +28,20 @@
|
|||
//!
|
||||
//! # Examples
|
||||
//!
|
||||
//! An example to parse a JPEG file:
|
||||
//! An example to parse a JPEG/TIFF file:
|
||||
//!
|
||||
//! ```
|
||||
//! let file = std::fs::File::open("tests/exif.jpg").unwrap();
|
||||
//! let mut reader = std::io::BufReader::new(&file);
|
||||
//! let buf = exif::get_exif_attr_from_jpeg(&mut reader).unwrap();
|
||||
//! let (fields, _) = exif::parse_exif(&buf).unwrap();
|
||||
//! let mut buf = Vec::new();
|
||||
//! let (fields, _) = exif::parse_image(&mut reader, &mut buf).unwrap();
|
||||
//! for f in fields {
|
||||
//! println!("{} {} {:?}", f.tag, f.thumbnail, f.value);
|
||||
//! }
|
||||
//! ```
|
||||
|
||||
pub use error::Error;
|
||||
pub use image::parse_image;
|
||||
pub use jpeg::get_exif_attr as get_exif_attr_from_jpeg;
|
||||
pub use tag::{Context, Tag};
|
||||
pub use tiff::Field;
|
||||
|
@ -54,6 +55,7 @@ mod tmacro;
|
|||
|
||||
mod endian;
|
||||
mod error;
|
||||
mod image;
|
||||
mod jpeg;
|
||||
pub mod tag;
|
||||
mod tiff;
|
||||
|
|
|
@ -35,6 +35,8 @@ use value::get_type_info;
|
|||
const TIFF_BE: u16 = 0x4d4d;
|
||||
const TIFF_LE: u16 = 0x4949;
|
||||
const TIFF_FORTY_TWO: u16 = 0x002a;
|
||||
const TIFF_BE_SIG: [u8; 4] = [0x4d, 0x4d, 0x00, 0x2a];
|
||||
const TIFF_LE_SIG: [u8; 4] = [0x49, 0x49, 0x2a, 0x00];
|
||||
|
||||
/// A TIFF field.
|
||||
#[derive(Debug)]
|
||||
|
@ -149,6 +151,10 @@ fn parse_ifd<E>(data: &[u8], offset: usize, ctx: Context, thumbnail: bool)
|
|||
Ok(fields)
|
||||
}
|
||||
|
||||
pub fn is_tiff(buf: &[u8]) -> bool {
|
||||
buf.starts_with(&TIFF_BE_SIG) || buf.starts_with(&TIFF_LE_SIG)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use error::Error;
|
||||
|
|
Loading…
Reference in New Issue