diff --git a/src/tag.rs b/src/tag.rs index 005fcf5..5cd35fc 100644 --- a/src/tag.rs +++ b/src/tag.rs @@ -89,15 +89,13 @@ impl fmt::Display for Tag { #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum Context { /// TIFF attributes defined in the TIFF Rev. 6.0 specification. - Tiff, // 0th IFD + Tiff, // 0th/1st IFD /// Exif attributes. - Exif, // 0th IFD -- Exif IFD + Exif, // 0th/1st IFD -- Exif IFD /// GPS attributes. - Gps, // 0th IFD -- GPS IFD + Gps, // 0th/1st IFD -- GPS IFD /// Interoperability attributes. - Interop, // 0th IFD -- Exif IFD -- Interoperability IFD - /// TIFF fields in the 1st IFD, which represents the thumbnail image. - Thumb, // 1st IFD + Interop, // 0th/1st IFD -- Exif IFD -- Interoperability IFD } struct TagInfo { @@ -149,7 +147,8 @@ generate_well_known_tag_constants!( /// structure of Exif data and will not be returned to the user. (InteropIFDPointer, 0xa005, "Interoperability IFD pointer"), - // TIFF attributes [EXIF23 4.6.4 Table 4 and 4.6.8 Table 17]. + // 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"), @@ -175,16 +174,14 @@ generate_well_known_tag_constants!( (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"), + (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"), - // Thumbnail Tiff attributes [EXIF23 4.6.4 Table 4 and 4.6.8 Table 21]. - // Exif IFD attributes [EXIF23 4.6.5 Table 7 and 4.6.8 Table 18]. |Context::Exif| diff --git a/src/tiff.rs b/src/tiff.rs index eb027f6..c40ae24 100644 --- a/src/tiff.rs +++ b/src/tiff.rs @@ -39,7 +39,11 @@ const TIFF_FORTY_TWO: u16 = 0x002a; /// A TIFF field. #[derive(Debug)] pub struct Field<'a> { + /// The tag of this field. pub tag: Tag, + /// False for the primary image and true for the thumbnail. + pub thumbnail: bool, + /// The value of this field. pub value: Value<'a>, } @@ -63,11 +67,11 @@ fn parse_exif_sub(data: &[u8]) return Err(Error::InvalidFormat("Invalid forty two")); } let ifd_offset = E::loadu32(data, 4) as usize; - parse_ifd::(data, ifd_offset, Context::Tiff) + parse_ifd::(data, ifd_offset, Context::Tiff, false) } // Parse IFD [EXIF23 4.6.2]. -fn parse_ifd(data: &[u8], offset: usize, ctx: Context) +fn parse_ifd(data: &[u8], offset: usize, ctx: Context, thumbnail: bool) -> Result, Error> where E: Endian { // Count (the number of the entries). if data.len() < offset || data.len() - offset < 2 { @@ -108,16 +112,19 @@ fn parse_ifd(data: &[u8], offset: usize, ctx: Context) // element of the field. let tag = Tag(ctx, tag); if tag == tag::ExifIFDPointer { - let mut v = try!(parse_ifd::(data, ofs, Context::Exif)); + let mut v = try!( + parse_ifd::(data, ofs, Context::Exif, thumbnail)); fields.append(&mut v); } else if tag == tag::GPSInfoIFDPointer { - let mut v = try!(parse_ifd::(data, ofs, Context::Gps)); + let mut v = try!( + parse_ifd::(data, ofs, Context::Gps, thumbnail)); fields.append(&mut v); } else if tag == tag::InteropIFDPointer { - let mut v = try!(parse_ifd::(data, ofs, Context::Interop)); + let mut v = try!( + parse_ifd::(data, ofs, Context::Interop, thumbnail)); fields.append(&mut v); } else { - fields.push(Field { tag: tag, value: val }); + fields.push(Field { tag: tag, thumbnail: thumbnail, value: val }); } } @@ -127,11 +134,11 @@ fn parse_ifd(data: &[u8], offset: usize, ctx: Context) } let next_ifd_offset = E::loadu32(data, offset + 2 + count * 12) as usize; if next_ifd_offset != 0 { - if ctx != Context::Tiff { + if ctx != Context::Tiff || thumbnail { return Err(Error::InvalidFormat("Unexpected next IFD")); } let mut v = try!( - parse_ifd::(data, next_ifd_offset, Context::Thumb)); + parse_ifd::(data, next_ifd_offset, Context::Tiff, true)); fields.append(&mut v); }