Add `Tag::TagName`s and deprecate `tag::TagName`s.
This commit is contained in:
parent
1ad83d8a82
commit
26a64361b3
|
@ -29,7 +29,7 @@ extern crate exif;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
|
|
||||||
use exif::{DateTime, Reader, Value, tag};
|
use exif::{DateTime, Reader, Value, Tag};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let file = File::open("tests/exif.jpg").unwrap();
|
let file = File::open("tests/exif.jpg").unwrap();
|
||||||
|
@ -37,11 +37,11 @@ fn main() {
|
||||||
|
|
||||||
// To obtain a string representation, `Value::display_as` can be used
|
// To obtain a string representation, `Value::display_as` can be used
|
||||||
// for any tag.
|
// for any tag.
|
||||||
let tag_list = [tag::ExifVersion,
|
let tag_list = [Tag::ExifVersion,
|
||||||
tag::PixelXDimension,
|
Tag::PixelXDimension,
|
||||||
tag::XResolution,
|
Tag::XResolution,
|
||||||
tag::ImageDescription,
|
Tag::ImageDescription,
|
||||||
tag::DateTime];
|
Tag::DateTime];
|
||||||
for &tag in tag_list.iter() {
|
for &tag in tag_list.iter() {
|
||||||
if let Some(field) = reader.get_field(tag, false) {
|
if let Some(field) = reader.get_field(tag, false) {
|
||||||
println!("{}: {}", field.tag, field.value.display_as(field.tag));
|
println!("{}: {}", field.tag, field.value.display_as(field.tag));
|
||||||
|
@ -50,7 +50,7 @@ fn main() {
|
||||||
|
|
||||||
// To get unsigned integer value(s) from either of BYTE, SHORT,
|
// To get unsigned integer value(s) from either of BYTE, SHORT,
|
||||||
// or LONG, `Value::get_uint` or `Value::iter_uint` can be used.
|
// or LONG, `Value::get_uint` or `Value::iter_uint` can be used.
|
||||||
if let Some(field) = reader.get_field(tag::PixelXDimension, false) {
|
if let Some(field) = reader.get_field(Tag::PixelXDimension, false) {
|
||||||
if let Some(width) = field.value.get_uint(0) {
|
if let Some(width) = field.value.get_uint(0) {
|
||||||
println!("Valid width of the image is {}.", width);
|
println!("Valid width of the image is {}.", width);
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ fn main() {
|
||||||
|
|
||||||
// To convert a Rational or SRational to an f64, `Rational::to_f64`
|
// To convert a Rational or SRational to an f64, `Rational::to_f64`
|
||||||
// or `SRational::to_f64` can be used.
|
// or `SRational::to_f64` can be used.
|
||||||
if let Some(field) = reader.get_field(tag::XResolution, false) {
|
if let Some(field) = reader.get_field(Tag::XResolution, false) {
|
||||||
match field.value {
|
match field.value {
|
||||||
Value::Rational(ref vec) if !vec.is_empty() =>
|
Value::Rational(ref vec) if !vec.is_empty() =>
|
||||||
println!("X resolution is {}.", vec[0].to_f64()),
|
println!("X resolution is {}.", vec[0].to_f64()),
|
||||||
|
@ -67,7 +67,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// To parse a DateTime-like field, `DateTime::from_ascii` can be used.
|
// To parse a DateTime-like field, `DateTime::from_ascii` can be used.
|
||||||
if let Some(field) = reader.get_field(tag::DateTime, false) {
|
if let Some(field) = reader.get_field(Tag::DateTime, false) {
|
||||||
match field.value {
|
match field.value {
|
||||||
Value::Ascii(ref vec) if !vec.is_empty() => {
|
Value::Ascii(ref vec) if !vec.is_empty() => {
|
||||||
if let Ok(datetime) = DateTime::from_ascii(vec[0]) {
|
if let Ok(datetime) = DateTime::from_ascii(vec[0]) {
|
||||||
|
|
|
@ -50,6 +50,8 @@
|
||||||
//! * Enum Error has two new variants: TooBig and NotSupported.
|
//! * Enum Error has two new variants: TooBig and NotSupported.
|
||||||
//! * Value::Undefined has the 2nd member to keep the offset of the value.
|
//! * Value::Undefined has the 2nd member to keep the offset of the value.
|
||||||
//! * Struct DateTime has two new fields: nanosecond and offset.
|
//! * Struct DateTime has two new fields: nanosecond and offset.
|
||||||
|
//! * The tag constants have been changed to associated constants of
|
||||||
|
//! struct `Tag`. Use `Tag::TagName` instead of `tag::TagName`.
|
||||||
|
|
||||||
pub use error::Error;
|
pub use error::Error;
|
||||||
pub use jpeg::get_exif_attr as get_exif_attr_from_jpeg;
|
pub use jpeg::get_exif_attr as get_exif_attr_from_jpeg;
|
||||||
|
|
|
@ -130,7 +130,6 @@ mod tests {
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::BufReader;
|
use std::io::BufReader;
|
||||||
use value::Value;
|
use value::Value;
|
||||||
use tag_priv::constants as tag;
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
static TIFF_ASCII: &'static [u8] =
|
static TIFF_ASCII: &'static [u8] =
|
||||||
|
@ -185,7 +184,7 @@ mod tests {
|
||||||
fn get_field() {
|
fn get_field() {
|
||||||
let file = File::open("tests/exif.jpg").unwrap();
|
let file = File::open("tests/exif.jpg").unwrap();
|
||||||
let reader = Reader::new(&mut BufReader::new(&file)).unwrap();
|
let reader = Reader::new(&mut BufReader::new(&file)).unwrap();
|
||||||
assert_pat!(reader.get_field(tag::ExifVersion, false).unwrap().value,
|
assert_pat!(reader.get_field(Tag::ExifVersion, false).unwrap().value,
|
||||||
Value::Undefined(b"0230", _));
|
Value::Undefined(b"0230", _));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
30
src/tag.rs
30
src/tag.rs
|
@ -31,6 +31,10 @@ use value::Value;
|
||||||
use util::{atou16, isupper};
|
use util::{atou16, isupper};
|
||||||
|
|
||||||
/// A tag of a TIFF field.
|
/// A tag of a TIFF field.
|
||||||
|
///
|
||||||
|
/// Some well-known tags are provided as associated constants of
|
||||||
|
/// this type. The constant names follow the Exif specification
|
||||||
|
/// but not the Rust naming conventions.
|
||||||
//
|
//
|
||||||
// This is not an enum to keep safety and API stability, while
|
// This is not an enum to keep safety and API stability, while
|
||||||
// supporting unknown tag numbers. This comment is based on the
|
// supporting unknown tag numbers. This comment is based on the
|
||||||
|
@ -130,6 +134,15 @@ macro_rules! generate_well_known_tag_constants {
|
||||||
// <https://github.com/rust-lang/rust/issues/25207>.
|
// <https://github.com/rust-lang/rust/issues/25207>.
|
||||||
pub mod constants {
|
pub mod constants {
|
||||||
use super::{Context, Tag};
|
use super::{Context, Tag};
|
||||||
|
$($(
|
||||||
|
$( #[$attr] )*
|
||||||
|
#[allow(non_upper_case_globals)]
|
||||||
|
#[deprecated(since = "0.3.0", note = "use `Tag::TagName` instead of `tag::TagName`")]
|
||||||
|
pub const $name: Tag = Tag($ctx, $num);
|
||||||
|
)+)+
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Tag {
|
||||||
$($(
|
$($(
|
||||||
$( #[$attr] )*
|
$( #[$attr] )*
|
||||||
#[allow(non_upper_case_globals)]
|
#[allow(non_upper_case_globals)]
|
||||||
|
@ -165,7 +178,7 @@ macro_rules! generate_well_known_tag_constants {
|
||||||
fn get_tag_info(tag: Tag) -> Option<&'static tag_info::TagInfo> {
|
fn get_tag_info(tag: Tag) -> Option<&'static tag_info::TagInfo> {
|
||||||
match tag {
|
match tag {
|
||||||
$($(
|
$($(
|
||||||
constants::$name => Some(&tag_info::$name),
|
Tag::$name => Some(&tag_info::$name),
|
||||||
)+)+
|
)+)+
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
|
@ -1269,7 +1282,6 @@ fn d_sub_ascii(w: &mut fmt::Write, bytes: &[u8]) -> fmt::Result {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use tag;
|
|
||||||
use value::Rational;
|
use value::Rational;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
@ -1283,19 +1295,19 @@ mod tests {
|
||||||
}
|
}
|
||||||
// Matching against a constant. Test if this compiles.
|
// Matching against a constant. Test if this compiles.
|
||||||
match Tag(Context::Tiff, 0x132) {
|
match Tag(Context::Tiff, 0x132) {
|
||||||
tag::DateTime => {},
|
Tag::DateTime => {},
|
||||||
_ => panic!("failed to match Tag"),
|
_ => panic!("failed to match Tag"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn default_value() {
|
fn default_value() {
|
||||||
assert_pat!(tag::DateTime.default_value(), None);
|
assert_pat!(Tag::DateTime.default_value(), None);
|
||||||
match tag::BitsPerSample.default_value() {
|
match Tag::BitsPerSample.default_value() {
|
||||||
Some(Value::Short(v)) => assert_eq!(v, &[8, 8, 8]),
|
Some(Value::Short(v)) => assert_eq!(v, &[8, 8, 8]),
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
}
|
}
|
||||||
match tag::XResolution.default_value() {
|
match Tag::XResolution.default_value() {
|
||||||
Some(Value::Rational(v)) => {
|
Some(Value::Rational(v)) => {
|
||||||
assert_eq!(v.len(), 1);
|
assert_eq!(v.len(), 1);
|
||||||
assert_eq!(v[0].num, 72);
|
assert_eq!(v[0].num, 72);
|
||||||
|
@ -1303,15 +1315,15 @@ mod tests {
|
||||||
},
|
},
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
}
|
}
|
||||||
match tag::FileSource.default_value() {
|
match Tag::FileSource.default_value() {
|
||||||
Some(Value::Undefined(v, _)) => assert_eq!(v, &[3]),
|
Some(Value::Undefined(v, _)) => assert_eq!(v, &[3]),
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
}
|
}
|
||||||
match tag::GPSAltitudeRef.default_value() {
|
match Tag::GPSAltitudeRef.default_value() {
|
||||||
Some(Value::Byte(v)) => assert_eq!(v, &[0]),
|
Some(Value::Byte(v)) => assert_eq!(v, &[0]),
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
}
|
}
|
||||||
match tag::GPSSpeedRef.default_value() {
|
match Tag::GPSSpeedRef.default_value() {
|
||||||
Some(Value::Ascii(v)) => assert_eq!(v, &[b"K"]),
|
Some(Value::Ascii(v)) => assert_eq!(v, &[b"K"]),
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ use std::fmt;
|
||||||
|
|
||||||
use endian::{Endian, BigEndian, LittleEndian};
|
use endian::{Endian, BigEndian, LittleEndian};
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use tag;
|
|
||||||
use tag_priv::{Context, Tag};
|
use tag_priv::{Context, Tag};
|
||||||
use value::Value;
|
use value::Value;
|
||||||
use value::get_type_info;
|
use value::get_type_info;
|
||||||
|
@ -120,11 +119,11 @@ fn parse_ifd<'a, E>(fields: &mut Vec<Field<'a>>, data: &'a [u8],
|
||||||
// recursively defined.
|
// recursively defined.
|
||||||
let tag = Tag(ctx, tag);
|
let tag = Tag(ctx, tag);
|
||||||
match tag {
|
match tag {
|
||||||
tag::ExifIFDPointer => try!(parse_child_ifd::<E>(
|
Tag::ExifIFDPointer => try!(parse_child_ifd::<E>(
|
||||||
fields, data, &val, Context::Exif, thumbnail)),
|
fields, data, &val, Context::Exif, thumbnail)),
|
||||||
tag::GPSInfoIFDPointer => try!(parse_child_ifd::<E>(
|
Tag::GPSInfoIFDPointer => try!(parse_child_ifd::<E>(
|
||||||
fields, data, &val, Context::Gps, thumbnail)),
|
fields, data, &val, Context::Gps, thumbnail)),
|
||||||
tag::InteropIFDPointer => try!(parse_child_ifd::<E>(
|
Tag::InteropIFDPointer => try!(parse_child_ifd::<E>(
|
||||||
fields, data, &val, Context::Interop, thumbnail)),
|
fields, data, &val, Context::Interop, thumbnail)),
|
||||||
_ => fields.push(Field { tag: tag, thumbnail: thumbnail,
|
_ => fields.push(Field { tag: tag, thumbnail: thumbnail,
|
||||||
value: val }),
|
value: val }),
|
||||||
|
|
|
@ -81,12 +81,12 @@ impl<'a> Value<'a> {
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// use exif::{Value, tag};
|
/// use exif::{Value, Tag};
|
||||||
/// let val = Value::Undefined(b"0231", 0);
|
/// let val = Value::Undefined(b"0231", 0);
|
||||||
/// assert_eq!(format!("{}", val.display_as(tag::ExifVersion)),
|
/// assert_eq!(format!("{}", val.display_as(Tag::ExifVersion)),
|
||||||
/// "2.31");
|
/// "2.31");
|
||||||
/// let val = Value::Short(vec![2]);
|
/// let val = Value::Short(vec![2]);
|
||||||
/// assert_eq!(format!("{}", val.display_as(tag::ResolutionUnit)),
|
/// assert_eq!(format!("{}", val.display_as(Tag::ResolutionUnit)),
|
||||||
/// "pixels per inch");
|
/// "pixels per inch");
|
||||||
/// ```
|
/// ```
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -31,7 +31,7 @@ use std::slice;
|
||||||
|
|
||||||
use endian::{Endian, BigEndian, LittleEndian};
|
use endian::{Endian, BigEndian, LittleEndian};
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use tag_priv::{Context, Tag, constants as tag};
|
use tag_priv::{Context, Tag};
|
||||||
use tiff::{Field, TIFF_BE_SIG, TIFF_LE_SIG};
|
use tiff::{Field, TIFF_BE_SIG, TIFF_LE_SIG};
|
||||||
use value::Value;
|
use value::Value;
|
||||||
|
|
||||||
|
@ -97,17 +97,17 @@ impl<'a> Writer<'a> {
|
||||||
pub fn push_field(&mut self, field: &'a Field) {
|
pub fn push_field(&mut self, field: &'a Field) {
|
||||||
match *field {
|
match *field {
|
||||||
// Ignore the tags for the internal data structure.
|
// Ignore the tags for the internal data structure.
|
||||||
Field { tag: tag::ExifIFDPointer, .. } |
|
Field { tag: Tag::ExifIFDPointer, .. } |
|
||||||
Field { tag: tag::GPSInfoIFDPointer, .. } |
|
Field { tag: Tag::GPSInfoIFDPointer, .. } |
|
||||||
Field { tag: tag::InteropIFDPointer, .. } => {},
|
Field { tag: Tag::InteropIFDPointer, .. } => {},
|
||||||
// These tags are synthesized from the actual strip/tile data.
|
// These tags are synthesized from the actual strip/tile data.
|
||||||
Field { tag: tag::StripOffsets, .. } |
|
Field { tag: Tag::StripOffsets, .. } |
|
||||||
Field { tag: tag::StripByteCounts, .. } |
|
Field { tag: Tag::StripByteCounts, .. } |
|
||||||
Field { tag: tag::TileOffsets, .. } |
|
Field { tag: Tag::TileOffsets, .. } |
|
||||||
Field { tag: tag::TileByteCounts, .. } => {},
|
Field { tag: Tag::TileByteCounts, .. } => {},
|
||||||
// These tags are synthesized from the actual JPEG thumbnail.
|
// These tags are synthesized from the actual JPEG thumbnail.
|
||||||
Field { tag: tag::JPEGInterchangeFormat, .. } |
|
Field { tag: Tag::JPEGInterchangeFormat, .. } |
|
||||||
Field { tag: tag::JPEGInterchangeFormatLength, .. } => {},
|
Field { tag: Tag::JPEGInterchangeFormatLength, .. } => {},
|
||||||
// Other normal tags.
|
// Other normal tags.
|
||||||
Field { tag: Tag(Context::Tiff, _), thumbnail: false, .. } =>
|
Field { tag: Tag(Context::Tiff, _), thumbnail: false, .. } =>
|
||||||
self.tiff_fields.push(field),
|
self.tiff_fields.push(field),
|
||||||
|
@ -246,13 +246,13 @@ fn synthesize_fields<W>(w: &mut W, ws: WriterState, thumbnail: bool,
|
||||||
|
|
||||||
if let Some(strips) = ws.strips {
|
if let Some(strips) = ws.strips {
|
||||||
strip_offsets = Field {
|
strip_offsets = Field {
|
||||||
tag: tag::StripOffsets,
|
tag: Tag::StripOffsets,
|
||||||
thumbnail: thumbnail,
|
thumbnail: thumbnail,
|
||||||
value: Value::Long(vec![0; strips.len()]),
|
value: Value::Long(vec![0; strips.len()]),
|
||||||
};
|
};
|
||||||
ws.tiff_fields.push(&strip_offsets);
|
ws.tiff_fields.push(&strip_offsets);
|
||||||
strip_byte_counts = Field {
|
strip_byte_counts = Field {
|
||||||
tag: tag::StripByteCounts,
|
tag: Tag::StripByteCounts,
|
||||||
thumbnail: thumbnail,
|
thumbnail: thumbnail,
|
||||||
value: Value::Long(
|
value: Value::Long(
|
||||||
strips.iter().map(|s| s.len() as u32).collect()),
|
strips.iter().map(|s| s.len() as u32).collect()),
|
||||||
|
@ -261,13 +261,13 @@ fn synthesize_fields<W>(w: &mut W, ws: WriterState, thumbnail: bool,
|
||||||
}
|
}
|
||||||
if let Some(tiles) = ws.tiles {
|
if let Some(tiles) = ws.tiles {
|
||||||
tile_offsets = Field {
|
tile_offsets = Field {
|
||||||
tag: tag::TileOffsets,
|
tag: Tag::TileOffsets,
|
||||||
thumbnail: thumbnail,
|
thumbnail: thumbnail,
|
||||||
value: Value::Long(vec![0; tiles.len()]),
|
value: Value::Long(vec![0; tiles.len()]),
|
||||||
};
|
};
|
||||||
ws.tiff_fields.push(&tile_offsets);
|
ws.tiff_fields.push(&tile_offsets);
|
||||||
tile_byte_counts = Field {
|
tile_byte_counts = Field {
|
||||||
tag: tag::TileByteCounts,
|
tag: Tag::TileByteCounts,
|
||||||
thumbnail: thumbnail,
|
thumbnail: thumbnail,
|
||||||
value: Value::Long(
|
value: Value::Long(
|
||||||
tiles.iter().map(|s| s.len() as u32).collect()),
|
tiles.iter().map(|s| s.len() as u32).collect()),
|
||||||
|
@ -276,13 +276,13 @@ fn synthesize_fields<W>(w: &mut W, ws: WriterState, thumbnail: bool,
|
||||||
}
|
}
|
||||||
if let Some(jpeg) = ws.jpeg {
|
if let Some(jpeg) = ws.jpeg {
|
||||||
jpeg_offset = Field {
|
jpeg_offset = Field {
|
||||||
tag: tag::JPEGInterchangeFormat,
|
tag: Tag::JPEGInterchangeFormat,
|
||||||
thumbnail: thumbnail,
|
thumbnail: thumbnail,
|
||||||
value: Value::Long(vec![0]),
|
value: Value::Long(vec![0]),
|
||||||
};
|
};
|
||||||
ws.tiff_fields.push(&jpeg_offset);
|
ws.tiff_fields.push(&jpeg_offset);
|
||||||
jpeg_length = Field {
|
jpeg_length = Field {
|
||||||
tag: tag::JPEGInterchangeFormatLength,
|
tag: Tag::JPEGInterchangeFormatLength,
|
||||||
thumbnail: thumbnail,
|
thumbnail: thumbnail,
|
||||||
value: Value::Long(vec![jpeg.len() as u32]),
|
value: Value::Long(vec![jpeg.len() as u32]),
|
||||||
};
|
};
|
||||||
|
@ -301,7 +301,7 @@ fn synthesize_fields<W>(w: &mut W, ws: WriterState, thumbnail: bool,
|
||||||
if exif_fields_len > 0 {
|
if exif_fields_len > 0 {
|
||||||
ws.exif_ifd_offset = try!(reserve_ifd(w, exif_fields_len));
|
ws.exif_ifd_offset = try!(reserve_ifd(w, exif_fields_len));
|
||||||
exif_in_tiff = Field {
|
exif_in_tiff = Field {
|
||||||
tag: tag::ExifIFDPointer,
|
tag: Tag::ExifIFDPointer,
|
||||||
thumbnail: thumbnail,
|
thumbnail: thumbnail,
|
||||||
value: Value::Long(vec![ws.exif_ifd_offset]),
|
value: Value::Long(vec![ws.exif_ifd_offset]),
|
||||||
};
|
};
|
||||||
|
@ -310,7 +310,7 @@ fn synthesize_fields<W>(w: &mut W, ws: WriterState, thumbnail: bool,
|
||||||
if gps_fields_len > 0 {
|
if gps_fields_len > 0 {
|
||||||
ws.gps_ifd_offset = try!(reserve_ifd(w, gps_fields_len));
|
ws.gps_ifd_offset = try!(reserve_ifd(w, gps_fields_len));
|
||||||
gps_in_tiff = Field {
|
gps_in_tiff = Field {
|
||||||
tag: tag::GPSInfoIFDPointer,
|
tag: Tag::GPSInfoIFDPointer,
|
||||||
thumbnail: thumbnail,
|
thumbnail: thumbnail,
|
||||||
value: Value::Long(vec![ws.gps_ifd_offset]),
|
value: Value::Long(vec![ws.gps_ifd_offset]),
|
||||||
};
|
};
|
||||||
|
@ -319,7 +319,7 @@ fn synthesize_fields<W>(w: &mut W, ws: WriterState, thumbnail: bool,
|
||||||
if interop_fields_len > 0 {
|
if interop_fields_len > 0 {
|
||||||
ws.interop_ifd_offset = try!(reserve_ifd(w, interop_fields_len));
|
ws.interop_ifd_offset = try!(reserve_ifd(w, interop_fields_len));
|
||||||
interop_in_exif = Field {
|
interop_in_exif = Field {
|
||||||
tag: tag::InteropIFDPointer,
|
tag: Tag::InteropIFDPointer,
|
||||||
thumbnail: thumbnail,
|
thumbnail: thumbnail,
|
||||||
value: Value::Long(vec![ws.interop_ifd_offset]),
|
value: Value::Long(vec![ws.interop_ifd_offset]),
|
||||||
};
|
};
|
||||||
|
@ -442,19 +442,19 @@ fn write_ifd_and_fields<W, E>(
|
||||||
try!(E::writeu32(&mut ifd, valofs));
|
try!(E::writeu32(&mut ifd, valofs));
|
||||||
try!(w.write_all(&valbuf));
|
try!(w.write_all(&valbuf));
|
||||||
}
|
}
|
||||||
if f.tag == tag::StripOffsets {
|
if f.tag == Tag::StripOffsets {
|
||||||
strip_offsets_offset = match valbuf.len() {
|
strip_offsets_offset = match valbuf.len() {
|
||||||
0...4 => ifd_offset + ifd.len() as u32 - 4,
|
0...4 => ifd_offset + ifd.len() as u32 - 4,
|
||||||
_ => try!(get_offset(w)) - valbuf.len() as u32,
|
_ => try!(get_offset(w)) - valbuf.len() as u32,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if f.tag == tag::TileOffsets {
|
if f.tag == Tag::TileOffsets {
|
||||||
tile_offsets_offset = match valbuf.len() {
|
tile_offsets_offset = match valbuf.len() {
|
||||||
0...4 => ifd_offset + ifd.len() as u32 - 4,
|
0...4 => ifd_offset + ifd.len() as u32 - 4,
|
||||||
_ => try!(get_offset(w)) - valbuf.len() as u32,
|
_ => try!(get_offset(w)) - valbuf.len() as u32,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if f.tag == tag::JPEGInterchangeFormat {
|
if f.tag == Tag::JPEGInterchangeFormat {
|
||||||
jpeg_offset = ifd_offset + ifd.len() as u32 - 4;
|
jpeg_offset = ifd_offset + ifd.len() as u32 - 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -594,7 +594,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn primary() {
|
fn primary() {
|
||||||
let image_desc = Field {
|
let image_desc = Field {
|
||||||
tag: tag::ImageDescription,
|
tag: Tag::ImageDescription,
|
||||||
thumbnail: false,
|
thumbnail: false,
|
||||||
value: Value::Ascii(vec![b"Sample"]),
|
value: Value::Ascii(vec![b"Sample"]),
|
||||||
};
|
};
|
||||||
|
@ -613,7 +613,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn primary_exif_only() {
|
fn primary_exif_only() {
|
||||||
let exif_ver = Field {
|
let exif_ver = Field {
|
||||||
tag: tag::ExifVersion,
|
tag: Tag::ExifVersion,
|
||||||
thumbnail: false,
|
thumbnail: false,
|
||||||
value: Value::Undefined(b"0231", 0),
|
value: Value::Undefined(b"0231", 0),
|
||||||
};
|
};
|
||||||
|
@ -686,22 +686,22 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn primary_and_thumbnail() {
|
fn primary_and_thumbnail() {
|
||||||
let image_desc = Field {
|
let image_desc = Field {
|
||||||
tag: tag::ImageDescription,
|
tag: Tag::ImageDescription,
|
||||||
thumbnail: false,
|
thumbnail: false,
|
||||||
value: Value::Ascii(vec![b"Sample"]),
|
value: Value::Ascii(vec![b"Sample"]),
|
||||||
};
|
};
|
||||||
let exif_ver = Field {
|
let exif_ver = Field {
|
||||||
tag: tag::ExifVersion,
|
tag: Tag::ExifVersion,
|
||||||
thumbnail: false,
|
thumbnail: false,
|
||||||
value: Value::Undefined(b"0231", 0),
|
value: Value::Undefined(b"0231", 0),
|
||||||
};
|
};
|
||||||
let gps_ver = Field {
|
let gps_ver = Field {
|
||||||
tag: tag::GPSVersionID,
|
tag: Tag::GPSVersionID,
|
||||||
thumbnail: false,
|
thumbnail: false,
|
||||||
value: Value::Byte(vec![2, 3, 0, 0]),
|
value: Value::Byte(vec![2, 3, 0, 0]),
|
||||||
};
|
};
|
||||||
let interop_index = Field {
|
let interop_index = Field {
|
||||||
tag: tag::InteroperabilityIndex,
|
tag: Tag::InteroperabilityIndex,
|
||||||
thumbnail: false,
|
thumbnail: false,
|
||||||
value: Value::Ascii(vec![b"ABC"]),
|
value: Value::Ascii(vec![b"ABC"]),
|
||||||
};
|
};
|
||||||
|
@ -738,7 +738,7 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn write_twice() {
|
fn write_twice() {
|
||||||
let image_desc = Field {
|
let image_desc = Field {
|
||||||
tag: tag::ImageDescription,
|
tag: Tag::ImageDescription,
|
||||||
thumbnail: false,
|
thumbnail: false,
|
||||||
value: Value::Ascii(vec![b"Sample"]),
|
value: Value::Ascii(vec![b"Sample"]),
|
||||||
};
|
};
|
||||||
|
|
|
@ -37,7 +37,7 @@ use std::path::Path;
|
||||||
|
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
use exif::Error;
|
use exif::Error;
|
||||||
use exif::{Reader, Value, tag};
|
use exif::{Reader, Value, Tag};
|
||||||
use exif::experimental::Writer;
|
use exif::experimental::Writer;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -122,8 +122,8 @@ fn rwr_compare<P>(path: P) where P: AsRef<Path> {
|
||||||
assert_eq!(f1.tag, f2.tag);
|
assert_eq!(f1.tag, f2.tag);
|
||||||
assert_eq!(f1.thumbnail, f2.thumbnail);
|
assert_eq!(f1.thumbnail, f2.thumbnail);
|
||||||
match f1.tag {
|
match f1.tag {
|
||||||
tag::StripOffsets | tag::TileOffsets |
|
Tag::StripOffsets | Tag::TileOffsets |
|
||||||
tag::JPEGInterchangeFormat => continue,
|
Tag::JPEGInterchangeFormat => continue,
|
||||||
_ => {},
|
_ => {},
|
||||||
}
|
}
|
||||||
compare_field_value(&f1.value, &f2.value);
|
compare_field_value(&f1.value, &f2.value);
|
||||||
|
@ -177,9 +177,9 @@ fn compare_field_value(value1: &Value, value2: &Value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_strips(reader: &Reader, thumbnail: bool) -> Option<Vec<&[u8]>> {
|
fn get_strips(reader: &Reader, thumbnail: bool) -> Option<Vec<&[u8]>> {
|
||||||
let offsets = reader.get_field(tag::StripOffsets, thumbnail)
|
let offsets = reader.get_field(Tag::StripOffsets, thumbnail)
|
||||||
.and_then(|f| f.value.iter_uint());
|
.and_then(|f| f.value.iter_uint());
|
||||||
let counts = reader.get_field(tag::StripByteCounts, thumbnail)
|
let counts = reader.get_field(Tag::StripByteCounts, thumbnail)
|
||||||
.and_then(|f| f.value.iter_uint());
|
.and_then(|f| f.value.iter_uint());
|
||||||
let (offsets, counts) = match (offsets, counts) {
|
let (offsets, counts) = match (offsets, counts) {
|
||||||
(Some(offsets), Some(counts)) => (offsets, counts),
|
(Some(offsets), Some(counts)) => (offsets, counts),
|
||||||
|
@ -194,9 +194,9 @@ fn get_strips(reader: &Reader, thumbnail: bool) -> Option<Vec<&[u8]>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_tiles(reader: &Reader, thumbnail: bool) -> Option<Vec<&[u8]>> {
|
fn get_tiles(reader: &Reader, thumbnail: bool) -> Option<Vec<&[u8]>> {
|
||||||
let offsets = reader.get_field(tag::TileOffsets, thumbnail)
|
let offsets = reader.get_field(Tag::TileOffsets, thumbnail)
|
||||||
.and_then(|f| f.value.iter_uint());
|
.and_then(|f| f.value.iter_uint());
|
||||||
let counts = reader.get_field(tag::TileByteCounts, thumbnail)
|
let counts = reader.get_field(Tag::TileByteCounts, thumbnail)
|
||||||
.and_then(|f| f.value.iter_uint());
|
.and_then(|f| f.value.iter_uint());
|
||||||
let (offsets, counts) = match (offsets, counts) {
|
let (offsets, counts) = match (offsets, counts) {
|
||||||
(Some(offsets), Some(counts)) => (offsets, counts),
|
(Some(offsets), Some(counts)) => (offsets, counts),
|
||||||
|
@ -211,9 +211,9 @@ fn get_tiles(reader: &Reader, thumbnail: bool) -> Option<Vec<&[u8]>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_jpeg(reader: &Reader, thumbnail: bool) -> Option<&[u8]> {
|
fn get_jpeg(reader: &Reader, thumbnail: bool) -> Option<&[u8]> {
|
||||||
let offset = reader.get_field(tag::JPEGInterchangeFormat, thumbnail)
|
let offset = reader.get_field(Tag::JPEGInterchangeFormat, thumbnail)
|
||||||
.and_then(|f| f.value.get_uint(0));
|
.and_then(|f| f.value.get_uint(0));
|
||||||
let len = reader.get_field(tag::JPEGInterchangeFormatLength, thumbnail)
|
let len = reader.get_field(Tag::JPEGInterchangeFormatLength, thumbnail)
|
||||||
.and_then(|f| f.value.get_uint(0));
|
.and_then(|f| f.value.get_uint(0));
|
||||||
let (offset, len) = match (offset, len) {
|
let (offset, len) = match (offset, len) {
|
||||||
(Some(offset), Some(len)) => (offset as usize, len as usize),
|
(Some(offset), Some(len)) => (offset as usize, len as usize),
|
||||||
|
|
Loading…
Reference in New Issue