use super::rational::*;
use std::fmt;
use std::result::Result;
use std::io;
#[derive(Debug)]
pub struct ExifData {
pub mime: String,
pub entries: Vec<ExifEntry>,
}
#[derive(Debug)]
pub enum ExifError {
IoError(io::Error),
FileTypeUnknown,
JpegWithoutExif(String),
TiffTruncated,
TiffBadPreamble(String),
IfdTruncated,
ExifIfdTruncated(String),
ExifIfdEntryNotFound,
}
#[derive(Clone, Debug)]
pub struct IfdEntry {
pub namespace: Namespace,
pub tag: u16,
pub format: IfdFormat,
pub count: u32,
pub data: Vec<u8>,
pub ifd_data: Vec<u8>,
pub ext_data: Vec<u8>,
pub le: bool,
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Namespace {
Standard = 0x0000,
Nikon = 0x0001,
Canon = 0x0002,
}
#[derive(Copy, Clone, Debug, PartialEq, Hash)]
pub enum ExifTag {
UnknownToMe = 0x0000ffff,
ImageDescription = 0x0000010e,
Make = 0x0000010f,
Model = 0x00000110,
Orientation = 0x00000112,
XResolution = 0x0000011a,
YResolution = 0x0000011b,
ResolutionUnit = 0x00000128,
Software = 0x00000131,
DateTime = 0x00000132,
HostComputer = 0x0000013c,
WhitePoint = 0x0000013e,
PrimaryChromaticities = 0x0000013f,
YCbCrCoefficients = 0x00000211,
ReferenceBlackWhite = 0x00000214,
Copyright = 0x00008298,
ExifOffset = 0x00008769,
GPSOffset = 0x00008825,
ExposureTime = 0x0000829a,
FNumber = 0x0000829d,
ExposureProgram = 0x00008822,
SpectralSensitivity = 0x00008824,
ISOSpeedRatings = 0x00008827,
OECF = 0x00008828,
SensitivityType = 0x00008830,
ExifVersion = 0x00009000,
DateTimeOriginal = 0x00009003,
DateTimeDigitized = 0x00009004,
ShutterSpeedValue = 0x00009201,
ApertureValue = 0x00009202,
BrightnessValue = 0x00009203,
ExposureBiasValue = 0x00009204,
MaxApertureValue = 0x00009205,
SubjectDistance = 0x00009206,
MeteringMode = 0x00009207,
LightSource = 0x00009208,
Flash = 0x00009209,
FocalLength = 0x0000920a,
SubjectArea = 0x00009214,
MakerNote = 0x0000927c,
UserComment = 0x00009286,
FlashPixVersion = 0x0000a000,
ColorSpace = 0x0000a001,
RelatedSoundFile = 0x0000a004,
FlashEnergy = 0x0000a20b,
FocalPlaneXResolution = 0x0000a20e,
FocalPlaneYResolution = 0x0000a20f,
FocalPlaneResolutionUnit = 0x0000a210,
SubjectLocation = 0x0000a214,
ExposureIndex = 0x0000a215,
SensingMethod = 0x0000a217,
FileSource = 0x0000a300,
SceneType = 0x0000a301,
CFAPattern = 0x0000a302,
CustomRendered = 0x0000a401,
ExposureMode = 0x0000a402,
WhiteBalanceMode = 0x0000a403,
DigitalZoomRatio = 0x0000a404,
FocalLengthIn35mmFilm = 0x0000a405,
SceneCaptureType = 0x0000a406,
GainControl = 0x0000a407,
Contrast = 0x0000a408,
Saturation = 0x0000a409,
Sharpness = 0x0000a40a,
DeviceSettingDescription = 0x0000a40b,
SubjectDistanceRange = 0x0000a40c,
ImageUniqueID = 0x0000a420,
LensSpecification = 0x0000a432,
LensMake = 0x0000a433,
LensModel = 0x0000a434,
Gamma = 0xa500,
GPSVersionID = 0x00000,
GPSLatitudeRef = 0x00001,
GPSLatitude = 0x00002,
GPSLongitudeRef = 0x00003,
GPSLongitude = 0x00004,
GPSAltitudeRef = 0x00005,
GPSAltitude = 0x00006,
GPSTimeStamp = 0x00007,
GPSSatellites = 0x00008,
GPSStatus = 0x00009,
GPSMeasureMode = 0x0000a,
GPSDOP = 0x0000b,
GPSSpeedRef = 0x0000c,
GPSSpeed = 0x0000d,
GPSTrackRef = 0x0000e,
GPSTrack = 0x0000f,
GPSImgDirectionRef = 0x000010,
GPSImgDirection = 0x000011,
GPSMapDatum = 0x000012,
GPSDestLatitudeRef = 0x000013,
GPSDestLatitude = 0x000014,
GPSDestLongitudeRef = 0x000015,
GPSDestLongitude = 0x000016,
GPSDestBearingRef = 0x000017,
GPSDestBearing = 0x000018,
GPSDestDistanceRef = 0x000019,
GPSDestDistance = 0x00001a,
GPSProcessingMethod = 0x00001b,
GPSAreaInformation = 0x00001c,
GPSDateStamp = 0x00001d,
GPSDifferential = 0x00001e,
}
impl Eq for ExifTag {}
impl fmt::Display for ExifTag {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", match *self {
ExifTag::ImageDescription => "Image Description",
ExifTag::Make => "Manufacturer",
ExifTag::HostComputer => "Host computer",
ExifTag::Model => "Model",
ExifTag::Orientation => "Orientation",
ExifTag::XResolution => "X Resolution",
ExifTag::YResolution => "Y Resolution",
ExifTag::ResolutionUnit => "Resolution Unit",
ExifTag::Software => "Software",
ExifTag::DateTime => "Image date",
ExifTag::WhitePoint => "White Point",
ExifTag::PrimaryChromaticities => "Primary Chromaticities",
ExifTag::YCbCrCoefficients => "YCbCr Coefficients",
ExifTag::ReferenceBlackWhite => "Reference Black/White",
ExifTag::Copyright => "Copyright",
ExifTag::ExifOffset => "This image has an Exif SubIFD",
ExifTag::GPSOffset => "This image has a GPS SubIFD",
ExifTag::ExposureTime => "Exposure time",
ExifTag::SensitivityType => "Sensitivity type",
ExifTag::FNumber => "Aperture",
ExifTag::ExposureProgram => "Exposure program",
ExifTag::SpectralSensitivity => "Spectral sensitivity",
ExifTag::ISOSpeedRatings => "ISO speed ratings",
ExifTag::OECF => "OECF",
ExifTag::ExifVersion => "Exif version",
ExifTag::DateTimeOriginal => "Date of original image",
ExifTag::DateTimeDigitized => "Date of image digitalization",
ExifTag::ShutterSpeedValue => "Shutter speed",
ExifTag::ApertureValue => "Aperture value",
ExifTag::BrightnessValue => "Brightness value",
ExifTag::ExposureBiasValue => "Exposure bias value",
ExifTag::MaxApertureValue => "Maximum aperture value",
ExifTag::SubjectDistance => "Subject distance",
ExifTag::MeteringMode => "Meteting mode",
ExifTag::LightSource => "Light source",
ExifTag::Flash => "Flash",
ExifTag::FocalLength => "Focal length",
ExifTag::SubjectArea => "Subject area",
ExifTag::MakerNote => "Maker note",
ExifTag::UserComment => "User comment",
ExifTag::FlashPixVersion => "Flashpix version",
ExifTag::ColorSpace => "Color space",
ExifTag::FlashEnergy => "Flash energy",
ExifTag::RelatedSoundFile => "Related sound file",
ExifTag::FocalPlaneXResolution => "Focal plane X resolution",
ExifTag::FocalPlaneYResolution => "Focal plane Y resolution",
ExifTag::FocalPlaneResolutionUnit => "Focal plane resolution unit",
ExifTag::SubjectLocation => "Subject location",
ExifTag::ExposureIndex => "Exposure index",
ExifTag::SensingMethod => "Sensing method",
ExifTag::FileSource => "File source",
ExifTag::SceneType => "Scene type",
ExifTag::CFAPattern => "CFA Pattern",
ExifTag::CustomRendered => "Custom rendered",
ExifTag::ExposureMode => "Exposure mode",
ExifTag::WhiteBalanceMode => "White balance mode",
ExifTag::DigitalZoomRatio => "Digital zoom ratio",
ExifTag::FocalLengthIn35mmFilm => "Equivalent focal length in 35mm",
ExifTag::SceneCaptureType => "Scene capture type",
ExifTag::GainControl => "Gain control",
ExifTag::Contrast => "Contrast",
ExifTag::Saturation => "Saturation",
ExifTag::Sharpness => "Sharpness",
ExifTag::LensSpecification => "Lens specification",
ExifTag::LensMake => "Lens manufacturer",
ExifTag::LensModel => "Lens model",
ExifTag::Gamma => "Gamma",
ExifTag::DeviceSettingDescription => "Device setting description",
ExifTag::SubjectDistanceRange => "Subject distance range",
ExifTag::ImageUniqueID => "Image unique ID",
ExifTag::GPSVersionID => "GPS version ID",
ExifTag::GPSLatitudeRef => "GPS latitude ref",
ExifTag::GPSLatitude => "GPS latitude",
ExifTag::GPSLongitudeRef => "GPS longitude ref",
ExifTag::GPSLongitude => "GPS longitude",
ExifTag::GPSAltitudeRef => "GPS altitude ref",
ExifTag::GPSAltitude => "GPS altitude",
ExifTag::GPSTimeStamp => "GPS timestamp",
ExifTag::GPSSatellites => "GPS satellites",
ExifTag::GPSStatus => "GPS status",
ExifTag::GPSMeasureMode => "GPS measure mode",
ExifTag::GPSDOP => "GPS Data Degree of Precision (DOP)",
ExifTag::GPSSpeedRef => "GPS speed ref",
ExifTag::GPSSpeed => "GPS speed",
ExifTag::GPSTrackRef => "GPS track ref",
ExifTag::GPSTrack => "GPS track",
ExifTag::GPSImgDirectionRef => "GPS image direction ref",
ExifTag::GPSImgDirection => "GPS image direction",
ExifTag::GPSMapDatum => "GPS map datum",
ExifTag::GPSDestLatitudeRef => "GPS destination latitude ref",
ExifTag::GPSDestLatitude => "GPS destination latitude",
ExifTag::GPSDestLongitudeRef => "GPS destination longitude ref",
ExifTag::GPSDestLongitude => "GPS destination longitude",
ExifTag::GPSDestBearingRef => "GPS destination bearing ref",
ExifTag::GPSDestBearing => "GPS destination bearing",
ExifTag::GPSDestDistanceRef => "GPS destination distance ref",
ExifTag::GPSDestDistance => "GPS destination distance",
ExifTag::GPSProcessingMethod => "GPS processing method",
ExifTag::GPSAreaInformation => "GPS area information",
ExifTag::GPSDateStamp => "GPS date stamp",
ExifTag::GPSDifferential => "GPS differential",
ExifTag::UnknownToMe => "Unknown to this library, or manufacturer-specific",
})
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum IfdFormat {
Unknown = 0,
U8 = 1,
Ascii = 2,
U16 = 3,
U32 = 4,
URational = 5,
I8 = 6,
Undefined = 7,
I16 = 8,
I32 = 9,
IRational = 10,
F32 = 11,
F64 = 12,
}
#[derive(Clone, Debug)]
pub struct ExifEntry {
pub namespace: Namespace,
pub ifd: IfdEntry,
pub tag: ExifTag,
pub value: TagValue,
pub unit: String,
pub value_more_readable: String,
}
#[derive(Clone, Debug)]
pub enum TagValue {
U8(Vec<u8>),
Ascii(String),
U16(Vec<u16>),
U32(Vec<u32>),
URational(Vec<URational>),
I8(Vec<i8>),
Undefined(Vec<u8>, bool),
I16(Vec<i16>),
I32(Vec<i32>),
IRational(Vec<IRational>),
F32(Vec<f32>),
F64(Vec<f64>),
Unknown(Vec<u8>, bool),
Invalid(Vec<u8>, bool, u16, u32)
}
impl TagValue {
pub fn to_i64(&self, index: usize) -> Option<i64> {
match *self {
TagValue::U8(ref v) => v.get(index).cloned().map(From::from),
TagValue::U16(ref v) => v.get(index).cloned().map(From::from),
TagValue::U32(ref v) => v.get(index).cloned().map(From::from),
TagValue::I8(ref v) => v.get(index).cloned().map(From::from),
TagValue::I16(ref v) => v.get(index).cloned().map(From::from),
TagValue::I32(ref v) => v.get(index).cloned().map(From::from),
_ => None,
}
}
pub fn to_f64(&self, index: usize) -> Option<f64> {
match *self {
TagValue::U8(ref v) => v.get(index).cloned().map(From::from),
TagValue::U16(ref v) => v.get(index).cloned().map(From::from),
TagValue::U32(ref v) => v.get(index).cloned().map(From::from),
TagValue::I8(ref v) => v.get(index).cloned().map(From::from),
TagValue::I16(ref v) => v.get(index).cloned().map(From::from),
TagValue::I32(ref v) => v.get(index).cloned().map(From::from),
TagValue::F32(ref v) => v.get(index).cloned().map(From::from),
TagValue::F64(ref v) => v.get(index).cloned().map(From::from),
TagValue::IRational(ref v) => v.get(index).cloned().map(|v| v.value()),
TagValue::URational(ref v) => v.get(index).cloned().map(|v| v.value()),
_ => None,
}
}
}
pub type ExifResult = Result<ExifData, ExifError>;
pub type ExifEntryResult = Result<Vec<ExifEntry>, ExifError>;