Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 25 additions & 1 deletion src/codecs/tiff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ where
dimensions: (u32, u32),
color_type: ColorType,
original_color_type: ExtendedColorType,
start_pos: u64,

// We only use an Option here so we can call with_limits on the decoder without moving.
inner: Option<Decoder<R>>,
Expand All @@ -40,7 +41,8 @@ where
R: BufRead + Seek,
{
/// Create a new `TiffDecoder`.
pub fn new(r: R) -> Result<TiffDecoder<R>, ImageError> {
pub fn new(mut r: R) -> Result<TiffDecoder<R>, ImageError> {
let start_pos = r.stream_position()?;
let mut inner = Decoder::new(r).map_err(ImageError::from_tiff_decode)?;

let dimensions = inner.dimensions().map_err(ImageError::from_tiff_decode)?;
Expand Down Expand Up @@ -115,6 +117,7 @@ where
dimensions,
color_type,
original_color_type,
start_pos,
inner: Some(inner),
})
}
Expand Down Expand Up @@ -266,6 +269,27 @@ impl<R: BufRead + Seek> ImageDecoder for TiffDecoder<R> {
}
}

fn exif_metadata(&mut self) -> ImageResult<Option<Vec<u8>>> {
let Some(decoder) = &mut self.inner else {
return Ok(None);
};

// Get access to the inner reader and remember the current position.
let reader = decoder.inner();
let last_pos = reader.stream_position()?;

// TIFF uses the same structure as EXIF, so we can just use the file itself
// as the source of decoding EXIF.
reader.seek(io::SeekFrom::Start(self.start_pos))?;
let mut result = Vec::new();
reader.read_to_end(&mut result)?;

// Restore the previous position.
reader.seek(io::SeekFrom::Start(last_pos))?;

Ok(Some(result))
}

fn xmp_metadata(&mut self) -> ImageResult<Option<Vec<u8>>> {
let Some(decoder) = &mut self.inner else {
return Ok(None);
Expand Down
16 changes: 16 additions & 0 deletions tests/metadata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ const EXPECTED_WEBP_TIFF_METADATA: &str = "<?xpacket begin='\u{feff}' id='W5M0Mp

const XMP_TIFF_PATH: &str = "tests/images/tiff/testsuite/l1_xmp.tiff";

const EXIF_TIFF_PATH: &str = "tests/images/tiff/testsuite/l1.tiff";

#[test]
#[cfg(feature = "png")]
fn test_read_xmp_png() -> Result<(), image::ImageError> {
Expand Down Expand Up @@ -64,3 +66,17 @@ fn test_read_xmp_tiff() -> Result<(), image::ImageError> {

Ok(())
}

#[test]
#[cfg(feature = "tiff")]
fn test_read_exif_tiff() -> Result<(), image::ImageError> {
let img_path = PathBuf::from_str(EXIF_TIFF_PATH).unwrap();

let data = fs::read(img_path)?;
let mut tiff_decoder = TiffDecoder::new(std::io::Cursor::new(&data))?;
let metadata = tiff_decoder.exif_metadata()?;
assert!(metadata.is_some());
assert_eq!(data, metadata.unwrap());

Ok(())
}
Loading