diff --git a/src/tag.rs b/src/tag.rs index dc253dd..b24bdf5 100644 --- a/src/tag.rs +++ b/src/tag.rs @@ -26,6 +26,8 @@ use std::fmt; +use value::Value; + /// A tag of a TIFF field. // // This is not an enum to keep safety and API stability, while @@ -64,6 +66,13 @@ impl Tag { pub fn description(&self) -> Option<&str> { get_tag_info(self).map(|ti| ti.desc) } + + /// Returns the default value of the tag. `None` is returned if + /// it is not defined in the standard or it depends on the context. + #[inline] + pub fn default_value(&self) -> Option { + get_tag_info(self).and_then(|ti| (&ti.default).into()) + } } impl fmt::Display for Tag { @@ -93,7 +102,7 @@ macro_rules! generate_well_known_tag_constants { $( |$ctx:path| $( // Copy the doc attribute to the actual definition. $( #[$attr:meta] )* - ($name:ident, $num:expr, $desc:expr) + ($name:ident, $num:expr, $defval:expr, $desc:expr) ),+, )+ ) => ( /// A module that contains Exif tag constants. @@ -122,15 +131,18 @@ macro_rules! generate_well_known_tag_constants { // Use a separate module to avoid name conflicts between // const Tag and static TagInfo. mod tag_info { + use value::DefaultValue; + pub struct TagInfo { pub name: &'static str, pub desc: &'static str, + pub default: DefaultValue, } $($( #[allow(non_upper_case_globals)] pub static $name: TagInfo = TagInfo { - name: stringify!($name), desc: $desc }; + name: stringify!($name), desc: $desc, default: $defval }; )+)+ } @@ -153,174 +165,321 @@ generate_well_known_tag_constants!( /// A pointer to the Exif IFD. This is used for the internal structure /// of Exif data and will not be returned to the user. - (ExifIFDPointer, 0x8769, "Exif IFD pointer"), + (ExifIFDPointer, 0x8769, DefaultValue::None, + "Exif IFD pointer"), /// A pointer to the GPS IFD. This is used for the internal structure /// of Exif data and will not be returned to the user. - (GPSInfoIFDPointer, 0x8825, "GPS Info IFD pointer"), + (GPSInfoIFDPointer, 0x8825, DefaultValue::None, + "GPS Info IFD pointer"), |Context::Exif| /// A pointer to the interoperability IFD. This is used for the internal /// structure of Exif data and will not be returned to the user. - (InteropIFDPointer, 0xa005, "Interoperability IFD pointer"), + (InteropIFDPointer, 0xa005, DefaultValue::None, + "Interoperability IFD pointer"), // TIFF primary and thumbnail attributes [EXIF23 4.6.4 Table 4, // 4.6.8 Table 17, and 4.6.8 Table 21]. |Context::Tiff| - (ImageWidth, 0x100, "Image width"), - (ImageLength, 0x101, "Image height"), - (BitsPerSample, 0x102, "Number of bits per component"), - (Compression, 0x103, "Compression scheme"), - (PhotometricInterpretation, 0x106, "Pixel composition"), - (ImageDescription, 0x10e, "Image title"), - (Make, 0x10f, "Manufacturer of image input equipment"), - (Model, 0x110, "Model of image input equipment"), - (StripOffsets, 0x111, "Image data location"), - (Orientation, 0x112, "Orientation of image"), - (SamplesPerPixel, 0x115, "Number of components"), - (RowsPerStrip, 0x116, "Number of rows per strip"), - (StripByteCounts, 0x117, "Bytes per compressed strip"), - (XResolution, 0x11a, "Image resolution in width direction"), - (YResolution, 0x11b, "Image resolution in height direction"), - (PlanarConfiguration, 0x11c, "Image data arrangement"), - (ResolutionUnit, 0x128, "Unit of X and Y resolution"), - (TransferFunction, 0x12d, "Transfer function"), - (Software, 0x131, "Software used"), - (DateTime, 0x132, "File change date and time"), - (Artist, 0x13b, "Person who created the image"), - (WhitePoint, 0x13e, "White point chromaticity"), - (PrimaryChromaticities, 0x13f, "Chromaticities of primaries"), - (JPEGInterchangeFormat, 0x201, "Offset to JPEG SOI"), - (JPEGInterchangeFormatLength, 0x202, "Bytes of JPEG data"), - (YCbCrCoefficients, 0x211, "Color space transformation matrix coefficients"), - (YCbCrSubSampling, 0x212, "Subsampling ratio of Y to C"), - (YCbCrPositioning, 0x213, "Y and C positioning"), - (ReferenceBlackWhite, 0x214, "Pair of black and white reference values"), - (Copyright, 0x8298, "Copyright holder"), + (ImageWidth, 0x100, DefaultValue::None, + "Image width"), + (ImageLength, 0x101, DefaultValue::None, + "Image height"), + (BitsPerSample, 0x102, DefaultValue::Short(&[8, 8, 8]), + "Number of bits per component"), + (Compression, 0x103, DefaultValue::None, + "Compression scheme"), + (PhotometricInterpretation, 0x106, DefaultValue::None, + "Pixel composition"), + (ImageDescription, 0x10e, DefaultValue::None, + "Image title"), + (Make, 0x10f, DefaultValue::None, + "Manufacturer of image input equipment"), + (Model, 0x110, DefaultValue::None, + "Model of image input equipment"), + (StripOffsets, 0x111, DefaultValue::None, + "Image data location"), + (Orientation, 0x112, DefaultValue::Short(&[1]), + "Orientation of image"), + (SamplesPerPixel, 0x115, DefaultValue::Short(&[3]), + "Number of components"), + (RowsPerStrip, 0x116, DefaultValue::None, + "Number of rows per strip"), + (StripByteCounts, 0x117, DefaultValue::None, + "Bytes per compressed strip"), + (XResolution, 0x11a, DefaultValue::Rational(&[(72, 1)]), + "Image resolution in width direction"), + (YResolution, 0x11b, DefaultValue::Rational(&[(72, 1)]), + "Image resolution in height direction"), + (PlanarConfiguration, 0x11c, DefaultValue::Short(&[1]), + "Image data arrangement"), + (ResolutionUnit, 0x128, DefaultValue::Short(&[2]), + "Unit of X and Y resolution"), + (TransferFunction, 0x12d, DefaultValue::None, + "Transfer function"), + (Software, 0x131, DefaultValue::None, + "Software used"), + (DateTime, 0x132, DefaultValue::None, + "File change date and time"), + (Artist, 0x13b, DefaultValue::None, + "Person who created the image"), + (WhitePoint, 0x13e, DefaultValue::None, + "White point chromaticity"), + (PrimaryChromaticities, 0x13f, DefaultValue::None, + "Chromaticities of primaries"), + (JPEGInterchangeFormat, 0x201, DefaultValue::None, + "Offset to JPEG SOI"), + (JPEGInterchangeFormatLength, 0x202, DefaultValue::None, + "Bytes of JPEG data"), + (YCbCrCoefficients, 0x211, DefaultValue::Unspecified, + "Color space transformation matrix coefficients"), + (YCbCrSubSampling, 0x212, DefaultValue::None, + "Subsampling ratio of Y to C"), + (YCbCrPositioning, 0x213, DefaultValue::Short(&[1]), + "Y and C positioning"), + (ReferenceBlackWhite, 0x214, DefaultValue::ContextDependent, + "Pair of black and white reference values"), + (Copyright, 0x8298, DefaultValue::None, + "Copyright holder"), // Exif IFD attributes [EXIF23 4.6.5 Table 7 and 4.6.8 Table 18]. |Context::Exif| - (ExposureTime, 0x829a, "Exposure time"), - (FNumber, 0x829d, "F number"), - (ExposureProgram, 0x8822, "Exposure program"), - (SpectralSensitivity, 0x8824, "Spectral sensitivity"), - (PhotographicSensitivity, 0x8827, "Photographic sensitivity"), - (OECF, 0x8828, "Optoelectric conversion factor"), - (SensitivityType, 0x8830, "Sensitivity type"), - (StandardOutputSensitivity, 0x8831, "Standard output sensitivity"), - (RecommendedExposureIndex, 0x8832, "Recommended exposure index"), - (ISOSpeed, 0x8833, "ISO speed"), - (ISOSpeedLatitudeyyy, 0x8834, "ISO speed latitude yyy"), - (ISOSpeedLatitudezzz, 0x8835, "ISO speed latitude zzz"), - (ExifVersion, 0x9000, "Exif version"), - (DateTimeOriginal, 0x9003, "Date and time of original data generation"), - (DateTimeDigitized, 0x9004, "Date and time of digital data generation"), - (OffsetTime, 0x9010, "Offset data of DateTime"), - (OffsetTimeOriginal, 0x9011, "Offset data of DateTimeOriginal"), - (OffsetTimeDigitized, 0x9012, "Offset data of DateTimeDigitized"), - (ComponentsConfiguration, 0x9101, "Meaning of each component"), - (CompressedBitsPerPixel, 0x9102, "Image compression mode"), - (ShutterSpeedValue, 0x9201, "Shutter speed"), - (ApertureValue, 0x9202, "Aperture"), - (BrightnessValue, 0x9203, "Brightness"), - (ExposureBiasValue, 0x9204, "Exposure bias"), - (MaxApertureValue, 0x9205, "Maximum lens aperture"), - (SubjectDistance, 0x9206, "Subject distance"), - (MeteringMode, 0x9207, "Metering mode"), - (LightSource, 0x9208, "Light source"), - (Flash, 0x9209, "Flash"), - (FocalLength, 0x920a, "Lens focal length"), - (SubjectArea, 0x9214, "Subject area"), - (MakerNote, 0x927c, "Manufacturer notes"), - (UserComment, 0x9286, "User comments"), - (SubSecTime, 0x9290, "DateTime subseconds"), - (SubSecTimeOriginal, 0x9291, "DateTimeOriginal subseconds"), - (SubSecTimeDigitized, 0x9292, "DateTimeDigitized subseconds"), - (Temperature, 0x9400, "Temperature"), - (Humidity, 0x9401, "Humidity"), - (Pressure, 0x9402, "Pressure"), - (WaterDepth, 0x9403, "Water depth"), - (Acceleration, 0x9404, "Acceleration"), - (CameraElevationAngle, 0x9405, "Camera elevation angle"), - (FlashpixVersion, 0xa000, "Supported Flashpix version"), - (ColorSpace, 0xa001, "Color space information"), - (PixelXDimension, 0xa002, "Valid image width"), - (PixelYDimension, 0xa003, "Valid image height"), - (RelatedSoundFile, 0xa004, "Related audio file"), - (FlashEnergy, 0xa20b, "Flash energy"), - (SpatialFrequencyResponse, 0xa20c, "Spatial frequency response"), - (FocalPlaneXResolution, 0xa20e, "Focal plane X resolution"), - (FocalPlaneYResolution, 0xa20f, "Focal plane Y resolution"), - (FocalPlaneResolutionUnit, 0xa210, "Focal plane resolution unit"), - (SubjectLocation, 0xa214, "Subject location"), - (ExposureIndex, 0xa215, "Exposure index"), - (SensingMethod, 0xa217, "Sensing method"), - (FileSource, 0xa300, "File source"), - (SceneType, 0xa301, "Scene type"), - (CFAPattern, 0xa302, "CFA pattern"), - (CustomRendered, 0xa401, "Custom image processing"), - (ExposureMode, 0xa402, "Exposure mode"), - (WhiteBalance, 0xa403, "White balance"), - (DigitalZoomRatio, 0xa404, "Digital zoom ratio"), - (FocalLengthIn35mmFilm, 0xa405, "Focal length in 35 mm film"), - (SceneCaptureType, 0xa406, "Scene capture type"), - (GainControl, 0xa407, "Gain control"), - (Contrast, 0xa408, "Contrast"), - (Saturation, 0xa409, "Saturation"), - (Sharpness, 0xa40a, "Sharpness"), - (DeviceSettingDescription, 0xa40b, "Device settings description"), - (SubjectDistanceRange, 0xa40c, "Subject distance range"), - (ImageUniqueID, 0xa420, "Unique image ID"), - (CameraOwnerName, 0xa430, "Camera owner name"), - (BodySerialNumber, 0xa431, "Body serial number"), - (LensSpecification, 0xa432, "Lens specification"), - (LensMake, 0xa433, "Lens make"), - (LensModel, 0xa434, "Lens model"), - (LensSerialNumber, 0xa435, "Lens serial number"), - (Gamma, 0xa500, "Gamma"), + (ExposureTime, 0x829a, DefaultValue::None, + "Exposure time"), + (FNumber, 0x829d, DefaultValue::None, + "F number"), + (ExposureProgram, 0x8822, DefaultValue::None, + "Exposure program"), + (SpectralSensitivity, 0x8824, DefaultValue::None, + "Spectral sensitivity"), + (PhotographicSensitivity, 0x8827, DefaultValue::None, + "Photographic sensitivity"), + (OECF, 0x8828, DefaultValue::None, + "Optoelectric conversion factor"), + (SensitivityType, 0x8830, DefaultValue::None, + "Sensitivity type"), + (StandardOutputSensitivity, 0x8831, DefaultValue::None, + "Standard output sensitivity"), + (RecommendedExposureIndex, 0x8832, DefaultValue::None, + "Recommended exposure index"), + (ISOSpeed, 0x8833, DefaultValue::None, + "ISO speed"), + (ISOSpeedLatitudeyyy, 0x8834, DefaultValue::None, + "ISO speed latitude yyy"), + (ISOSpeedLatitudezzz, 0x8835, DefaultValue::None, + "ISO speed latitude zzz"), + // The absence of this field means non-conformance to Exif, so the default + // value specified in the standard (e.g., "0231") should not apply. + (ExifVersion, 0x9000, DefaultValue::None, + "Exif version"), + (DateTimeOriginal, 0x9003, DefaultValue::None, + "Date and time of original data generation"), + (DateTimeDigitized, 0x9004, DefaultValue::None, + "Date and time of digital data generation"), + (OffsetTime, 0x9010, DefaultValue::None, + "Offset data of DateTime"), + (OffsetTimeOriginal, 0x9011, DefaultValue::None, + "Offset data of DateTimeOriginal"), + (OffsetTimeDigitized, 0x9012, DefaultValue::None, + "Offset data of DateTimeDigitized"), + (ComponentsConfiguration, 0x9101, DefaultValue::ContextDependent, + "Meaning of each component"), + (CompressedBitsPerPixel, 0x9102, DefaultValue::None, + "Image compression mode"), + (ShutterSpeedValue, 0x9201, DefaultValue::None, + "Shutter speed"), + (ApertureValue, 0x9202, DefaultValue::None, + "Aperture"), + (BrightnessValue, 0x9203, DefaultValue::None, + "Brightness"), + (ExposureBiasValue, 0x9204, DefaultValue::None, + "Exposure bias"), + (MaxApertureValue, 0x9205, DefaultValue::None, + "Maximum lens aperture"), + (SubjectDistance, 0x9206, DefaultValue::None, + "Subject distance"), + (MeteringMode, 0x9207, DefaultValue::Short(&[0]), + "Metering mode"), + (LightSource, 0x9208, DefaultValue::Short(&[0]), + "Light source"), + (Flash, 0x9209, DefaultValue::Unspecified, + "Flash"), + (FocalLength, 0x920a, DefaultValue::None, + "Lens focal length"), + (SubjectArea, 0x9214, DefaultValue::None, + "Subject area"), + (MakerNote, 0x927c, DefaultValue::None, + "Manufacturer notes"), + (UserComment, 0x9286, DefaultValue::None, + "User comments"), + (SubSecTime, 0x9290, DefaultValue::None, + "DateTime subseconds"), + (SubSecTimeOriginal, 0x9291, DefaultValue::None, + "DateTimeOriginal subseconds"), + (SubSecTimeDigitized, 0x9292, DefaultValue::None, + "DateTimeDigitized subseconds"), + (Temperature, 0x9400, DefaultValue::None, + "Temperature"), + (Humidity, 0x9401, DefaultValue::None, + "Humidity"), + (Pressure, 0x9402, DefaultValue::None, + "Pressure"), + (WaterDepth, 0x9403, DefaultValue::None, + "Water depth"), + (Acceleration, 0x9404, DefaultValue::None, + "Acceleration"), + (CameraElevationAngle, 0x9405, DefaultValue::None, + "Camera elevation angle"), + (FlashpixVersion, 0xa000, DefaultValue::Undefined(b"0100"), + "Supported Flashpix version"), + (ColorSpace, 0xa001, DefaultValue::Unspecified, + "Color space information"), + (PixelXDimension, 0xa002, DefaultValue::None, + "Valid image width"), + (PixelYDimension, 0xa003, DefaultValue::Unspecified, + "Valid image height"), + (RelatedSoundFile, 0xa004, DefaultValue::None, + "Related audio file"), + (FlashEnergy, 0xa20b, DefaultValue::None, + "Flash energy"), + (SpatialFrequencyResponse, 0xa20c, DefaultValue::None, + "Spatial frequency response"), + (FocalPlaneXResolution, 0xa20e, DefaultValue::None, + "Focal plane X resolution"), + (FocalPlaneYResolution, 0xa20f, DefaultValue::None, + "Focal plane Y resolution"), + (FocalPlaneResolutionUnit, 0xa210, DefaultValue::Short(&[2]), + "Focal plane resolution unit"), + (SubjectLocation, 0xa214, DefaultValue::None, + "Subject location"), + (ExposureIndex, 0xa215, DefaultValue::None, + "Exposure index"), + (SensingMethod, 0xa217, DefaultValue::None, + "Sensing method"), + (FileSource, 0xa300, DefaultValue::Undefined(&[3]), + "File source"), + (SceneType, 0xa301, DefaultValue::Undefined(&[1]), + "Scene type"), + (CFAPattern, 0xa302, DefaultValue::None, + "CFA pattern"), + (CustomRendered, 0xa401, DefaultValue::Short(&[0]), + "Custom image processing"), + (ExposureMode, 0xa402, DefaultValue::None, + "Exposure mode"), + (WhiteBalance, 0xa403, DefaultValue::None, + "White balance"), + (DigitalZoomRatio, 0xa404, DefaultValue::None, + "Digital zoom ratio"), + (FocalLengthIn35mmFilm, 0xa405, DefaultValue::None, + "Focal length in 35 mm film"), + (SceneCaptureType, 0xa406, DefaultValue::Short(&[0]), + "Scene capture type"), + (GainControl, 0xa407, DefaultValue::None, + "Gain control"), + (Contrast, 0xa408, DefaultValue::Short(&[0]), + "Contrast"), + (Saturation, 0xa409, DefaultValue::Short(&[0]), + "Saturation"), + (Sharpness, 0xa40a, DefaultValue::Short(&[0]), + "Sharpness"), + (DeviceSettingDescription, 0xa40b, DefaultValue::None, + "Device settings description"), + (SubjectDistanceRange, 0xa40c, DefaultValue::None, + "Subject distance range"), + (ImageUniqueID, 0xa420, DefaultValue::None, + "Unique image ID"), + (CameraOwnerName, 0xa430, DefaultValue::None, + "Camera owner name"), + (BodySerialNumber, 0xa431, DefaultValue::None, + "Body serial number"), + (LensSpecification, 0xa432, DefaultValue::None, + "Lens specification"), + (LensMake, 0xa433, DefaultValue::None, + "Lens make"), + (LensModel, 0xa434, DefaultValue::None, + "Lens model"), + (LensSerialNumber, 0xa435, DefaultValue::None, + "Lens serial number"), + (Gamma, 0xa500, DefaultValue::None, + "Gamma"), // GPS attributes [EXIF23 4.6.6 Table 15 and 4.6.8 Table 19]. |Context::Gps| - (GPSVersionID, 0x0, "GPS tag version"), - (GPSLatitudeRef, 0x1, "North or south latitude"), - (GPSLatitude, 0x2, "Latitude"), - (GPSLongitudeRef, 0x3, "East or West Longitude"), - (GPSLongitude, 0x4, "Longitude"), - (GPSAltitudeRef, 0x5, "Altitude reference"), - (GPSAltitude, 0x6, "Altitude"), - (GPSTimeStamp, 0x7, "GPS time (atomic clock)"), - (GPSSatellites, 0x8, "GPS satellites used for measurement"), - (GPSStatus, 0x9, "GPS receiver status"), - (GPSMeasureMode, 0xa, "GPS measurement mode"), - (GPSDOP, 0xb, "Measurement precision"), - (GPSSpeedRef, 0xc, "Speed unit"), - (GPSSpeed, 0xd, "Speed of GPS receiver"), - (GPSTrackRef, 0xe, "Reference for direction of movement"), - (GPSTrack, 0xf, "Direction of movement"), - (GPSImgDirectionRef, 0x10, "Reference for direction of image"), - (GPSImgDirection, 0x11, "Direction of image"), - (GPSMapDatum, 0x12, "Geodetic survey data used"), - (GPSDestLatitudeRef, 0x13, "Reference for latitude of destination"), - (GPSDestLatitude, 0x14, "Latitude of destination"), - (GPSDestLongitudeRef, 0x15, "Reference for longitude of destination"), - (GPSDestLongitude, 0x16, "Longitude of destination"), - (GPSDestBearingRef, 0x17, "Reference for bearing of destination"), - (GPSDestBearing, 0x18, "Bearing of destination"), - (GPSDestDistanceRef, 0x19, "Reference for distance to destination"), - (GPSDestDistance, 0x1a, "Distance to destination"), - (GPSProcessingMethod, 0x1b, "Name of GPS processing method"), - (GPSAreaInformation, 0x1c, "Name of GPS area"), - (GPSDateStamp, 0x1d, "GPS date"), - (GPSDifferential, 0x1e, "GPS differential correction"), - (GPSHPositioningError, 0x1f, "Horizontal positioning error"), + // Depends on the Exif version. + (GPSVersionID, 0x0, DefaultValue::ContextDependent, + "GPS tag version"), + (GPSLatitudeRef, 0x1, DefaultValue::None, + "North or south latitude"), + (GPSLatitude, 0x2, DefaultValue::None, + "Latitude"), + (GPSLongitudeRef, 0x3, DefaultValue::None, + "East or West Longitude"), + (GPSLongitude, 0x4, DefaultValue::None, + "Longitude"), + (GPSAltitudeRef, 0x5, DefaultValue::Byte(&[0]), + "Altitude reference"), + (GPSAltitude, 0x6, DefaultValue::None, + "Altitude"), + (GPSTimeStamp, 0x7, DefaultValue::None, + "GPS time (atomic clock)"), + (GPSSatellites, 0x8, DefaultValue::None, + "GPS satellites used for measurement"), + (GPSStatus, 0x9, DefaultValue::None, + "GPS receiver status"), + (GPSMeasureMode, 0xa, DefaultValue::None, + "GPS measurement mode"), + (GPSDOP, 0xb, DefaultValue::None, + "Measurement precision"), + (GPSSpeedRef, 0xc, DefaultValue::Ascii(&[b"K"]), + "Speed unit"), + (GPSSpeed, 0xd, DefaultValue::None, + "Speed of GPS receiver"), + (GPSTrackRef, 0xe, DefaultValue::Ascii(&[b"T"]), + "Reference for direction of movement"), + (GPSTrack, 0xf, DefaultValue::None, + "Direction of movement"), + (GPSImgDirectionRef, 0x10, DefaultValue::Ascii(&[b"T"]), + "Reference for direction of image"), + (GPSImgDirection, 0x11, DefaultValue::None, + "Direction of image"), + (GPSMapDatum, 0x12, DefaultValue::None, + "Geodetic survey data used"), + (GPSDestLatitudeRef, 0x13, DefaultValue::None, + "Reference for latitude of destination"), + (GPSDestLatitude, 0x14, DefaultValue::None, + "Latitude of destination"), + (GPSDestLongitudeRef, 0x15, DefaultValue::None, + "Reference for longitude of destination"), + (GPSDestLongitude, 0x16, DefaultValue::None, + "Longitude of destination"), + (GPSDestBearingRef, 0x17, DefaultValue::Ascii(&[b"T"]), + "Reference for bearing of destination"), + (GPSDestBearing, 0x18, DefaultValue::None, + "Bearing of destination"), + (GPSDestDistanceRef, 0x19, DefaultValue::Ascii(&[b"K"]), + "Reference for distance to destination"), + (GPSDestDistance, 0x1a, DefaultValue::None, + "Distance to destination"), + (GPSProcessingMethod, 0x1b, DefaultValue::None, + "Name of GPS processing method"), + (GPSAreaInformation, 0x1c, DefaultValue::None, + "Name of GPS area"), + (GPSDateStamp, 0x1d, DefaultValue::None, + "GPS date"), + (GPSDifferential, 0x1e, DefaultValue::None, + "GPS differential correction"), + (GPSHPositioningError, 0x1f, DefaultValue::None, + "Horizontal positioning error"), // Interoperability attributes [EXIF23 4.6.7 Table 16 and 4.6.8 Table 20]. |Context::Interop| - (InteroperabilityIndex, 0x1, "Interoperability identification"), + (InteroperabilityIndex, 0x1, DefaultValue::None, + "Interoperability identification"), ); #[cfg(test)] @@ -342,4 +501,33 @@ mod tests { _ => panic!("failed to match Tag"), } } + + #[test] + fn default_value() { + assert_pat!(tag::DateTime.default_value(), None); + match tag::BitsPerSample.default_value() { + Some(Value::Short(v)) => assert_eq!(v, &[8, 8, 8]), + _ => panic!(), + } + match tag::XResolution.default_value() { + Some(Value::Rational(v)) => { + assert_eq!(v.len(), 1); + assert_eq!(v[0].num, 72); + assert_eq!(v[0].denom, 1); + }, + _ => panic!(), + } + match tag::FileSource.default_value() { + Some(Value::Undefined(v)) => assert_eq!(v, &[3]), + _ => panic!(), + } + match tag::GPSAltitudeRef.default_value() { + Some(Value::Byte(v)) => assert_eq!(v, &[0]), + _ => panic!(), + } + match tag::GPSSpeedRef.default_value() { + Some(Value::Ascii(v)) => assert_eq!(v, &[b"K"]), + _ => panic!(), + } + } } diff --git a/src/value.rs b/src/value.rs index ec85441..f3f0c04 100644 --- a/src/value.rs +++ b/src/value.rs @@ -68,9 +68,43 @@ pub enum Value<'a> { Unknown(u16, u32, u32), } +// Static default values. +pub enum DefaultValue { + None, + Byte(&'static [u8]), + Ascii(&'static [&'static [u8]]), + Short(&'static [u16]), + Rational(&'static [(u32, u32)]), + Undefined(&'static [u8]), + // Depends on other tags, JPEG markers, etc. + ContextDependent, + // Unspecified in the Exif standard. + Unspecified, +} + +impl<'a> From<&'a DefaultValue> for Option> { + fn from(defval: &DefaultValue) -> Option { + match *defval { + DefaultValue::None => None, + DefaultValue::Byte(s) => Some(Value::Byte(s.to_vec())), + DefaultValue::Ascii(s) => Some(Value::Ascii(s.to_vec())), + DefaultValue::Short(s) => Some(Value::Short(s.to_vec())), + DefaultValue::Rational(s) => Some(Value::Rational( + s.iter().map(|&t| tuple2rational(t)).collect())), + DefaultValue::Undefined(s) => Some(Value::Undefined(s)), + DefaultValue::ContextDependent => None, + DefaultValue::Unspecified => None, + } + } +} + /// An unsigned rational number, which is a pair of 32-bit unsigned integers. pub struct Rational { pub num: u32, pub denom: u32 } +fn tuple2rational(t: (u32, u32)) -> Rational { + Rational { num: t.0, denom: t.1 } +} + impl fmt::Debug for Rational { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "Rational({}/{})", self.num, self.denom)