Skip to content

Commit 86fff31

Browse files
committed
Implement retrieving XMP metadata for tiff
1 parent c0d1781 commit 86fff31

File tree

3 files changed

+39
-0
lines changed

3 files changed

+39
-0
lines changed

src/codecs/tiff.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ use crate::error::{
2020
use crate::metadata::Orientation;
2121
use crate::{utils, ImageDecoder, ImageEncoder, ImageFormat};
2222

23+
const TAG_XML_PACKET: Tag = Tag::Unknown(700);
24+
2325
/// Decoder for TIFF images.
2426
pub struct TiffDecoder<R>
2527
where
@@ -264,6 +266,24 @@ impl<R: BufRead + Seek> ImageDecoder for TiffDecoder<R> {
264266
}
265267
}
266268

269+
fn xmp_metadata(&mut self) -> ImageResult<Option<Vec<u8>>> {
270+
let Some(decoder) = &mut self.inner else {
271+
return Ok(None);
272+
};
273+
274+
let value = match decoder.get_tag(TAG_XML_PACKET) {
275+
Ok(value) => value,
276+
Err(tiff::TiffError::FormatError(tiff::TiffFormatError::RequiredTagNotFound(_))) => {
277+
return Ok(None);
278+
}
279+
Err(err) => return Err(ImageError::from_tiff_decode(err)),
280+
};
281+
value
282+
.into_u8_vec()
283+
.map(Some)
284+
.map_err(ImageError::from_tiff_decode)
285+
}
286+
267287
fn orientation(&mut self) -> ImageResult<Orientation> {
268288
if let Some(decoder) = &mut self.inner {
269289
Ok(decoder
4.33 KB
Binary file not shown.

tests/metadata.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ use image::ImageDecoder;
66

77
#[cfg(feature = "png")]
88
use image::codecs::png::PngDecoder;
9+
#[cfg(feature = "tiff")]
10+
use image::codecs::tiff::TiffDecoder;
911
#[cfg(feature = "webp")]
1012
use image::codecs::webp::WebPDecoder;
1113

@@ -18,6 +20,9 @@ const EXPECTED_PNG_METADATA: &str = "<?xpacket begin='\u{feff}' id='W5M0MpCehiHz
1820
const XMP_WEBP_PATH: &str = "tests/images/webp/lossless_images/simple_xmp.webp";
1921
const EXPECTED_WEBP_METADATA: &str = "<?xpacket begin='\u{feff}' id='W5M0MpCehiHzreSzNTczkc9d'?>\n<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 13.25'>\n<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>\n\n <rdf:Description rdf:about=''\n xmlns:dc='http://purl.org/dc/elements/1.1/'>\n <dc:subject>\n <rdf:Bag>\n <rdf:li>sunset, mountains, nature</rdf:li>\n </rdf:Bag>\n </dc:subject>\n </rdf:Description>\n</rdf:RDF>\n</x:xmpmeta>\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n<?xpacket end='w'?>";
2022

23+
const XMP_TIFF_PATH: &str = "tests/images/tiff/testsuite/l1_xmp.tiff";
24+
const EXPECTED_METADATA_TIFF: &str = "<?xpacket begin='\u{feff}' id='W5M0MpCehiHzreSzNTczkc9d'?>\n<x:xmpmeta xmlns:x='adobe:ns:meta/' x:xmptk='Image::ExifTool 13.25'>\n<rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'>\n\n <rdf:Description rdf:about=''\n xmlns:dc='http://purl.org/dc/elements/1.1/'>\n <dc:subject>\n <rdf:Bag>\n <rdf:li>sunset, mountains, nature</rdf:li>\n </rdf:Bag>\n </dc:subject>\n </rdf:Description>\n</rdf:RDF>\n</x:xmpmeta>\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n<?xpacket end='w'?>";
25+
2126
#[test]
2227
#[cfg(feature = "png")]
2328
fn test_read_xmp_png() -> Result<(), image::ImageError> {
@@ -46,3 +51,17 @@ fn test_read_xmp_webp() -> Result<(), image::ImageError> {
4651

4752
Ok(())
4853
}
54+
55+
#[test]
56+
#[cfg(feature = "tiff")]
57+
fn test_read_xmp_tiff() -> Result<(), image::ImageError> {
58+
let img_path = PathBuf::from_str(XMP_TIFF_PATH).unwrap();
59+
60+
let data = fs::read(img_path)?;
61+
let mut tiff_decoder = TiffDecoder::new(std::io::Cursor::new(data))?;
62+
let metadata = tiff_decoder.xmp_metadata()?;
63+
assert!(metadata.is_some());
64+
assert_eq!(EXPECTED_METADATA_TIFF.as_bytes(), metadata.unwrap());
65+
66+
Ok(())
67+
}

0 commit comments

Comments
 (0)