diff --git a/src/encoder/mod.rs b/src/encoder/mod.rs index c56c012..93256d1 100644 --- a/src/encoder/mod.rs +++ b/src/encoder/mod.rs @@ -582,7 +582,7 @@ impl<'a, W: 'a + Write + Seek, T: ColorType, K: TiffKind> ImageEncoder<'a, W, T, )?; encoder.write_tag(Tag::XResolution, Rational { n: 1, d: 1 })?; encoder.write_tag(Tag::YResolution, Rational { n: 1, d: 1 })?; - encoder.write_tag(Tag::ResolutionUnit, ResolutionUnit::None.to_u16())?; + encoder.write_tag(Tag::ResolutionUnit, ResolutionUnit::None)?; Ok(ImageEncoder { encoder, diff --git a/src/encoder/tiff_value.rs b/src/encoder/tiff_value.rs index 16ab2c1..b40d0f4 100644 --- a/src/encoder/tiff_value.rs +++ b/src/encoder/tiff_value.rs @@ -1,6 +1,6 @@ use std::{borrow::Cow, io::Write, slice::from_ref}; -use crate::{bytecast, tags::Type, TiffError, TiffFormatError, TiffResult}; +use crate::{bytecast, tags, tags::Type, TiffError, TiffFormatError, TiffResult}; use super::writer::TiffWriter; @@ -458,6 +458,128 @@ impl TiffValue for str { } } +// FIXME: held up on reading the discriminant for all but the unknown variant. +// +// It needs to have `repr(u16)` to have a defined layout and then we may read the tag from its +// value representation by casting a u16 pointer to a pointer to the enum type. +// unsafe { *<*const _>::from(self).cast::() } +// But that is quite unsafe and needs careful review to maintain the safety requirements. Maybe we +// could get `bytemuck` to add a trait for this (it has `TransparentWrapper`) with a derive for +// enum types that have an explicit repr. +// +// This would allow returning borrowed data in more cases. For all types without an unknown, in all +// cases including as slices, and for all types with and unknown variant when we have a single +// value (either returning a borrowed discriminant or a borrowed value within `Unknown`). +impl TiffValue for tags::CompressionMethod { + const BYTE_LEN: u8 = ::BYTE_LEN; + const FIELD_TYPE: Type = Type::SHORT; + + fn count(&self) -> usize { + 1 + } + + fn data(&self) -> Cow<'_, [u8]> { + let bytes = self.to_u16().to_ne_bytes(); + Cow::Owned(bytes.to_vec()) + } +} + +impl TiffValue for tags::PhotometricInterpretation { + const BYTE_LEN: u8 = ::BYTE_LEN; + const FIELD_TYPE: Type = Type::SHORT; + + fn count(&self) -> usize { + 1 + } + + fn data(&self) -> Cow<'_, [u8]> { + self.to_u16().to_ne_bytes().to_vec().into() + } +} + +impl TiffValue for tags::PlanarConfiguration { + const BYTE_LEN: u8 = 2; + const FIELD_TYPE: Type = Type::SHORT; + + fn count(&self) -> usize { + 1 + } + + fn data(&self) -> Cow<'_, [u8]> { + self.to_u16().to_ne_bytes().to_vec().into() + } +} + +impl TiffValue for tags::Predictor { + const BYTE_LEN: u8 = ::BYTE_LEN; + const FIELD_TYPE: Type = Type::SHORT; + + fn count(&self) -> usize { + 1 + } + + fn data(&self) -> Cow<'_, [u8]> { + self.to_u16().to_ne_bytes().to_vec().into() + } +} + +impl TiffValue for tags::ResolutionUnit { + const BYTE_LEN: u8 = ::BYTE_LEN; + const FIELD_TYPE: Type = Type::SHORT; + + fn count(&self) -> usize { + 1 + } + + fn data(&self) -> Cow<'_, [u8]> { + self.to_u16().to_ne_bytes().to_vec().into() + } +} + +/// This is implemented for slices as the `SampleFormat` tag takes a count of `N`. +/// +/// Use `core::slice::from_ref` if you really need to write a single element. +/// +/// See: +impl TiffValue for [tags::SampleFormat] { + const BYTE_LEN: u8 = ::BYTE_LEN; + const FIELD_TYPE: Type = Type::SHORT; + + fn count(&self) -> usize { + self.len() + } + + fn data(&self) -> Cow<'_, [u8]> { + let mut buf: Vec = Vec::with_capacity(self.len() * 2); + for x in self { + buf.extend_from_slice(&x.to_u16().to_ne_bytes()); + } + Cow::Owned(buf) + } +} + +/// This is implemented for slices as the `ExtraSamples` tag takes a count of `N`. +/// +/// Use `core::slice::from_ref` if you really need to write a single element. +/// +/// See: +impl TiffValue for [tags::ExtraSamples] { + const BYTE_LEN: u8 = ::BYTE_LEN; + const FIELD_TYPE: Type = Type::SHORT; + + fn count(&self) -> usize { + self.len() + } + + fn data(&self) -> Cow<'_, [u8]> { + let mut buf: Vec = Vec::with_capacity(self.len() * 2); + for x in self { + buf.extend_from_slice(&x.to_u16().to_ne_bytes()); + } + Cow::Owned(buf) + } +} + // If you pass `&Vec<_>` then you'd get at first sight the complaint: // // `Vec` does not implement `TiffValue`