From ba1daa18b2261a7e251c60bfaaae4df02fde465e Mon Sep 17 00:00:00 2001 From: Farkal Date: Mon, 27 Jul 2020 11:29:09 +0200 Subject: [PATCH] Allow custom encoding process (#84) Simplify encoding of tags --- src/encoder/mod.rs | 52 +++++++++++++++++++++++++++--------------- tests/encode_images.rs | 10 +++++--- 2 files changed, 40 insertions(+), 22 deletions(-) diff --git a/src/encoder/mod.rs b/src/encoder/mod.rs index 22e39d3..df9a2a5 100644 --- a/src/encoder/mod.rs +++ b/src/encoder/mod.rs @@ -407,26 +407,9 @@ impl TiffEncoder { where [C::Inner]: TiffValue, { - let num_pix = usize::try_from(width)?.checked_mul(usize::try_from(height)?) - .ok_or_else(|| ::std::io::Error::new( - ::std::io::ErrorKind::InvalidInput, - "Image width * height exceeds usize"))?; - if data.len() < num_pix { - return Err(::std::io::Error::new( - ::std::io::ErrorKind::InvalidData, - "Input data slice is undersized for provided dimensions").into()); - } - let encoder = DirectoryEncoder::new(&mut self.writer)?; - let mut image: ImageEncoder = ImageEncoder::new(encoder, width, height)?; - - let mut idx = 0; - while image.next_strip_sample_count() > 0 { - let sample_count = usize::try_from(image.next_strip_sample_count())?; - image.write_strip(&data[idx..idx + sample_count])?; - idx += sample_count; - } - image.finish() + let image: ImageEncoder = ImageEncoder::new(encoder, width, height)?; + image.write_data(data) } } @@ -548,10 +531,14 @@ impl<'a, W: Write + Seek> Drop for DirectoryEncoder<'a, W> { /// # let mut file = std::io::Cursor::new(Vec::new()); /// # let image_data = vec![0; 100*100*3]; /// use tiff::encoder::*; +/// use tiff::tags::Tag; /// /// let mut tiff = TiffEncoder::new(&mut file).unwrap(); /// let mut image = tiff.new_image::(100, 100).unwrap(); /// +/// // You can encode tags here +/// image.encoder().write_tag(Tag::Artist, "Image-tiff").unwrap(); +/// /// let mut idx = 0; /// while image.next_strip_sample_count() > 0 { /// let sample_count = image.next_strip_sample_count() as usize; @@ -561,11 +548,13 @@ impl<'a, W: Write + Seek> Drop for DirectoryEncoder<'a, W> { /// image.finish().unwrap(); /// # } /// ``` +/// You can also call write_data function wich will encode by strip and finish pub struct ImageEncoder<'a, W: 'a + Write + Seek, C: ColorType> { encoder: DirectoryEncoder<'a, W>, strip_idx: u64, strip_count: u64, row_samples: u64, + width: u32, height: u32, rows_per_strip: u64, strip_offsets: Vec, @@ -608,6 +597,7 @@ impl<'a, W: 'a + Write + Seek, T: ColorType> ImageEncoder<'a, W, T> { strip_idx: 0, row_samples, rows_per_strip, + width, height, strip_offsets: Vec::new(), strip_byte_count: Vec::new(), @@ -652,6 +642,30 @@ impl<'a, W: 'a + Write + Seek, T: ColorType> ImageEncoder<'a, W, T> { Ok(()) } + /// Write strips from data + pub fn write_data(mut self, data: &[T::Inner]) -> TiffResult<()> + where + [T::Inner]: TiffValue, + { + let num_pix = usize::try_from(self.width)?.checked_mul(usize::try_from(self.height)?) + .ok_or_else(|| ::std::io::Error::new( + ::std::io::ErrorKind::InvalidInput, + "Image width * height exceeds usize"))?; + if data.len() < num_pix { + return Err(::std::io::Error::new( + ::std::io::ErrorKind::InvalidData, + "Input data slice is undersized for provided dimensions").into()); + } + let mut idx = 0; + while self.next_strip_sample_count() > 0 { + let sample_count = usize::try_from(self.next_strip_sample_count())?; + self.write_strip(&data[idx..idx + sample_count])?; + idx += sample_count; + } + self.finish()?; + Ok(()) + } + /// Set image resolution pub fn resolution(&mut self, unit: ResolutionUnit, value: Rational) { self.encoder.write_tag(Tag::ResolutionUnit, unit.to_u16()).unwrap(); diff --git a/tests/encode_images.rs b/tests/encode_images.rs index 9d1ecfd..9ba1cd3 100644 --- a/tests/encode_images.rs +++ b/tests/encode_images.rs @@ -1,6 +1,6 @@ extern crate tiff; -use tiff::decoder::{Decoder, DecodingResult}; +use tiff::decoder::{Decoder, DecodingResult, ifd}; use tiff::encoder::{colortype, TiffEncoder, SRational}; use tiff::ColorType; use tiff::tags::Tag; @@ -24,14 +24,18 @@ fn encode_decode() { { let mut tiff = TiffEncoder::new(&mut file).unwrap(); - tiff.write_image::(100, 100, &image_data) + let mut image = tiff.new_image::(100, 100) .unwrap(); + image.encoder().write_tag(Tag::Artist, "Image-tiff").unwrap(); + image.write_data(&image_data).unwrap(); + } { file.seek(SeekFrom::Start(0)).unwrap(); let mut decoder = Decoder::new(&mut file).unwrap(); assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8)); assert_eq!(decoder.dimensions().unwrap(), (100, 100)); + assert_eq!(decoder.get_tag(Tag::Artist).unwrap(), ifd::Value::Ascii("Image-tiff".into())); if let DecodingResult::U8(img_res) = decoder.read_image().unwrap() { assert_eq!(image_data, img_res); } else { @@ -259,4 +263,4 @@ fn test_multipage_image() { // check the dimensions of the image in the second page assert_eq!(img_decoder.dimensions().unwrap(), (3, 3)); } -} +} \ No newline at end of file