From 098b799a62586619f9aa55494f6ad19ef05583d3 Mon Sep 17 00:00:00 2001 From: Birk Tjelmeland Date: Tue, 26 Feb 2019 10:57:28 +0100 Subject: [PATCH] Fix string encoding and clean up --- src/encoder/colortype.rs | 30 ++++++++---------------------- src/encoder/mod.rs | 35 ++++++++++++++++++++++++----------- src/encoder/writer.rs | 6 ++++-- 3 files changed, 36 insertions(+), 35 deletions(-) diff --git a/src/encoder/colortype.rs b/src/encoder/colortype.rs index 3b4b739..bc52a3d 100644 --- a/src/encoder/colortype.rs +++ b/src/encoder/colortype.rs @@ -7,68 +7,54 @@ pub trait ColorType { /// The value of the tiff tag `PhotometricInterpretation` const TIFF_VALUE: PhotometricInterpretation; /// The value of the tiff tag `BitsPerSample` - fn bits_per_sample() -> Vec; + const BITS_PER_SAMPLE: &'static [u16]; } pub struct Gray8; impl ColorType for Gray8 { type Inner = u8; const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::BlackIsZero; - fn bits_per_sample() -> Vec { - vec![8] - } + const BITS_PER_SAMPLE: &'static [u16] = &[8]; } pub struct Gray16; impl ColorType for Gray16 { type Inner = u16; const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::BlackIsZero; - fn bits_per_sample() -> Vec { - vec![16] - } + const BITS_PER_SAMPLE: &'static [u16] = &[16]; } pub struct RGB8; impl ColorType for RGB8 { type Inner = u8; const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::RGB; - fn bits_per_sample() -> Vec { - vec![8,8,8] - } + const BITS_PER_SAMPLE: &'static [u16] = &[8, 8, 8]; } pub struct RGB16; impl ColorType for RGB16 { type Inner = u16; const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::RGB; - fn bits_per_sample() -> Vec { - vec![16,16,16] - } + const BITS_PER_SAMPLE: &'static [u16] = &[16, 16, 16]; } pub struct RGBA8; impl ColorType for RGBA8 { type Inner = u8; const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::RGB; - fn bits_per_sample() -> Vec { - vec![8,8,8,8] - } + const BITS_PER_SAMPLE: &'static [u16] = &[8, 8, 8, 8]; } pub struct RGBA16; impl ColorType for RGBA16 { type Inner = u16; const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::RGB; - fn bits_per_sample() -> Vec { - vec![16,16,16,16] - } + const BITS_PER_SAMPLE: &'static [u16] = &[16, 16, 16, 16]; } pub struct CMYK8; impl ColorType for CMYK8 { type Inner = u8; const TIFF_VALUE: PhotometricInterpretation = PhotometricInterpretation::CMYK; - fn bits_per_sample() -> Vec { - vec![8,8,8,8] - } + const BITS_PER_SAMPLE: &'static [u16] = &[8, 8, 8, 8]; } diff --git a/src/encoder/mod.rs b/src/encoder/mod.rs index 2a7a2a1..eeb9e1e 100644 --- a/src/encoder/mod.rs +++ b/src/encoder/mod.rs @@ -36,7 +36,7 @@ pub trait TiffValue { fn write(&self, writer: &mut TiffWriter) -> TiffResult<()>; } -impl TiffValue for &[u8] { +impl TiffValue for [u8] { const BYTE_LEN: u32 = 1; const FIELD_TYPE: ifd::Type = ifd::Type::BYTE; @@ -50,7 +50,7 @@ impl TiffValue for &[u8] { } } -impl TiffValue for &[u16] { +impl TiffValue for [u16] { const BYTE_LEN: u32 = 2; const FIELD_TYPE: ifd::Type = ifd::Type::SHORT; @@ -68,7 +68,7 @@ impl TiffValue for &[u16] { } } -impl TiffValue for &[u32] { +impl TiffValue for [u32] { const BYTE_LEN: u32 = 4; const FIELD_TYPE: ifd::Type = ifd::Type::LONG; @@ -86,7 +86,7 @@ impl TiffValue for &[u32] { } } -impl TiffValue for &[Rational] { +impl TiffValue for [Rational] { const BYTE_LEN: u32 = 8; const FIELD_TYPE: ifd::Type = ifd::Type::RATIONAL; @@ -95,7 +95,7 @@ impl TiffValue for &[Rational] { } fn write(&self, writer: &mut TiffWriter) -> TiffResult<()> { - for x in *self { + for x in self { x.write(writer)?; } Ok(()) @@ -168,7 +168,7 @@ impl TiffValue for str { } fn write(&self, writer: &mut TiffWriter) -> TiffResult<()> { - if self.is_ascii() { + if self.is_ascii() && !self.bytes().any(|b| b == 0) { writer.write_bytes(self.as_bytes())?; writer.write_u8(0)?; Ok(()) @@ -179,6 +179,19 @@ impl TiffValue for str { } } +impl<'a, T: TiffValue + ?Sized> TiffValue for &'a T { + const BYTE_LEN: u32 = T::BYTE_LEN; + const FIELD_TYPE: ifd::Type = T::FIELD_TYPE; + + fn count(&self) -> u32 { + (*self).count() + } + + fn write(&self, writer: &mut TiffWriter) -> TiffResult<()> { + (*self).write(writer) + } +} + /// Tiff encoder. /// /// With this type you can get a `DirectoryEncoder` or a `ImageEncoder` @@ -224,7 +237,7 @@ impl TiffEncoder { } /// Convenience function to write an entire image from memory. - pub fn write_image<'a, C: ColorType>(&mut self, width: u32, height: u32, data: &'a [C::Inner]) -> TiffResult<()> where &'a [C::Inner]: TiffValue { + pub fn write_image(&mut self, width: u32, height: u32, data: &[C::Inner]) -> TiffResult<()> where [C::Inner]: TiffValue { let encoder = DirectoryEncoder::new(&mut self.writer)?; let mut image: ImageEncoder = ImageEncoder::new(encoder, width, height).unwrap(); @@ -381,7 +394,7 @@ pub struct ImageEncoder<'a, W: Write + Seek, C: ColorType> { impl<'a, W: Write + Seek, T: ColorType> ImageEncoder<'a, W, T> { fn new(mut encoder: DirectoryEncoder<'a, W>, width: u32, height: u32) -> TiffResult> { - let row_samples = u64::from(width) * ::bits_per_sample().len() as u64; + let row_samples = u64::from(width) * ::BITS_PER_SAMPLE.len() as u64; let row_bytes = row_samples * u64::from(::BYTE_LEN); // As per tiff spec each strip should be about 8k long @@ -393,12 +406,12 @@ impl<'a, W: Write + Seek, T: ColorType> ImageEncoder<'a, W, T> { encoder.write_tag(Tag::ImageLength, height); encoder.write_tag(Tag::Compression, 1u16); - encoder.write_tag(Tag::BitsPerSample, &::bits_per_sample() as &[u16]); + encoder.write_tag(Tag::BitsPerSample, ::BITS_PER_SAMPLE); encoder.write_tag(Tag::PhotometricInterpretation, ::TIFF_VALUE as u16); encoder.write_tag(Tag::RowsPerStrip, rows_per_strip as u32); - encoder.write_tag(Tag::SamplesPerPixel, ::bits_per_sample().len() as u16); + encoder.write_tag(Tag::SamplesPerPixel, ::BITS_PER_SAMPLE.len() as u16); 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, 1u16); @@ -430,7 +443,7 @@ impl<'a, W: Write + Seek, T: ColorType> ImageEncoder<'a, W, T> { } /// Write a single strip. - pub fn write_strip<'b>(&mut self, value: &'b [T::Inner]) -> TiffResult<()> where &'b [T::Inner]: TiffValue { + pub fn write_strip(&mut self, value: &[T::Inner]) -> TiffResult<()> where [T::Inner]: TiffValue { // TODO: Compression let samples = self.next_strip_sample_count(); assert_eq!(value.len() as u64, samples); diff --git a/src/encoder/writer.rs b/src/encoder/writer.rs index 6739e32..1f0eef1 100644 --- a/src/encoder/writer.rs +++ b/src/encoder/writer.rs @@ -77,8 +77,10 @@ impl TiffWriter { } pub fn pad_word_boundary(&mut self) -> Result<(), io::Error> { - while self.offset % 4 != 0 { - self.writer.write_u8(0)?; + if self.offset % 4 != 0 { + let padding = [0, 0, 0]; + let padd_len = 4 - (self.offset % 4); + self.writer.write_all(&padding[..padd_len as usize])?; } Ok(())