Skip to content

Commit

Permalink
Add support for iterating over all tags (#255)
Browse files Browse the repository at this point in the history
  • Loading branch information
gschulze authored Nov 26, 2024
1 parent 96d3a02 commit ff52aea
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 5 deletions.
18 changes: 13 additions & 5 deletions src/decoder/mod.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -895,6 +894,15 @@ impl<R: Read + Seek> Decoder<R> {
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<Item = TiffResult<(Tag, ifd::Value)>> + '_ {
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(
Expand Down
82 changes: 82 additions & 0 deletions tests/encode_images.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Vec<_>>();
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())
Expand Down Expand Up @@ -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::<Vec<_>>();
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())
Expand Down

0 comments on commit ff52aea

Please sign in to comment.