From ff52aea06e3871777999c639a9732efb31342c58 Mon Sep 17 00:00:00 2001 From: Gunnar Schulze Date: Tue, 26 Nov 2024 04:34:11 +0100 Subject: [PATCH] Add support for iterating over all tags (#255) --- src/decoder/mod.rs | 18 +++++++--- tests/encode_images.rs | 82 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 5 deletions(-) diff --git a/src/decoder/mod.rs b/src/decoder/mod.rs index 8b5ffbc..2b8b0dd 100644 --- a/src/decoder/mod.rs +++ b/src/decoder/mod.rs @@ -1,17 +1,16 @@ use std::collections::{HashMap, HashSet}; use std::io::{self, Read, Seek}; +use crate::tags::{ + CompressionMethod, PhotometricInterpretation, PlanarConfiguration, Predictor, SampleFormat, + Tag, Type, +}; use crate::{ bytecast, ColorType, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError, UsageError, }; use self::ifd::Directory; use self::image::Image; -use crate::tags::{ - CompressionMethod, PhotometricInterpretation, PlanarConfiguration, Predictor, SampleFormat, - Tag, Type, -}; - use self::stream::{ByteOrder, EndianReader, SmartReader}; pub mod ifd; @@ -895,6 +894,15 @@ impl Decoder { self.get_tag(tag)?.into_string() } + /// Returns an iterator over all tags in the current image, along with their values. + pub fn tag_iter(&mut self) -> impl Iterator> + '_ { + self.image.ifd.as_ref().unwrap().iter().map(|(tag, entry)| { + entry + .val(&self.limits, self.bigtiff, &mut self.reader) + .map(|value| (*tag, value)) + }) + } + fn check_chunk_type(&self, expected: ChunkType) -> TiffResult<()> { if expected != self.image().chunk_type { return Err(TiffError::UsageError(UsageError::InvalidChunkType( diff --git a/tests/encode_images.rs b/tests/encode_images.rs index 532ed21..ee1e3c0 100644 --- a/tests/encode_images.rs +++ b/tests/encode_images.rs @@ -36,6 +36,47 @@ fn encode_decode() { let mut decoder = Decoder::new(&mut file).unwrap(); assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8)); assert_eq!(decoder.dimensions().unwrap(), (100, 100)); + + let mut all_tags = decoder + .tag_iter() + .filter_map(Result::ok) + .collect::>(); + all_tags.sort_by_key(|(t, _)| t.to_u16()); + assert_eq!( + all_tags, + vec![ + (Tag::ImageWidth, ifd::Value::Unsigned(100)), + (Tag::ImageLength, ifd::Value::Unsigned(100)), + ( + Tag::BitsPerSample, + ifd::Value::List(vec![ + ifd::Value::UnsignedBig(8), + ifd::Value::UnsignedBig(8), + ifd::Value::UnsignedBig(8) + ]) + ), + (Tag::Compression, ifd::Value::Unsigned(1)), + (Tag::PhotometricInterpretation, ifd::Value::Unsigned(2)), + (Tag::StripOffsets, ifd::Value::Unsigned(8)), + (Tag::SamplesPerPixel, ifd::Value::Unsigned(3)), + (Tag::RowsPerStrip, ifd::Value::Unsigned(3334)), + (Tag::StripByteCounts, ifd::Value::Unsigned(30000)), + (Tag::XResolution, ifd::Value::Rational(1, 1)), + (Tag::YResolution, ifd::Value::Rational(1, 1)), + (Tag::ResolutionUnit, ifd::Value::Unsigned(1)), + (Tag::Artist, ifd::Value::Ascii("Image-tiff".into())), + (Tag::Predictor, ifd::Value::Unsigned(1)), + ( + Tag::SampleFormat, + ifd::Value::List(vec![ + ifd::Value::UnsignedBig(1), + ifd::Value::UnsignedBig(1), + ifd::Value::UnsignedBig(1) + ]) + ), + ] + ); + assert_eq!( decoder.get_tag(Tag::Artist).unwrap(), ifd::Value::Ascii("Image-tiff".into()) @@ -75,6 +116,47 @@ fn encode_decode_big() { let mut decoder = Decoder::new(&mut file).unwrap(); assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8)); assert_eq!(decoder.dimensions().unwrap(), (100, 100)); + + let mut all_tags = decoder + .tag_iter() + .filter_map(Result::ok) + .collect::>(); + all_tags.sort_by_key(|(t, _)| t.to_u16()); + assert_eq!( + all_tags, + vec![ + (Tag::ImageWidth, ifd::Value::Unsigned(100)), + (Tag::ImageLength, ifd::Value::Unsigned(100)), + ( + Tag::BitsPerSample, + ifd::Value::List(vec![ + ifd::Value::Short(8), + ifd::Value::Short(8), + ifd::Value::Short(8) + ]) + ), + (Tag::Compression, ifd::Value::Unsigned(1)), + (Tag::PhotometricInterpretation, ifd::Value::Unsigned(2)), + (Tag::StripOffsets, ifd::Value::UnsignedBig(16)), + (Tag::SamplesPerPixel, ifd::Value::Unsigned(3)), + (Tag::RowsPerStrip, ifd::Value::Unsigned(3334)), + (Tag::StripByteCounts, ifd::Value::UnsignedBig(30000)), + (Tag::XResolution, ifd::Value::Rational(1, 1)), + (Tag::YResolution, ifd::Value::Rational(1, 1)), + (Tag::ResolutionUnit, ifd::Value::Unsigned(1)), + (Tag::Artist, ifd::Value::Ascii("Image-tiff".into())), + (Tag::Predictor, ifd::Value::Unsigned(1)), + ( + Tag::SampleFormat, + ifd::Value::List(vec![ + ifd::Value::Short(1), + ifd::Value::Short(1), + ifd::Value::Short(1) + ]) + ), + ] + ); + assert_eq!( decoder.get_tag(Tag::Artist).unwrap(), ifd::Value::Ascii("Image-tiff".into())