diff --git a/Cargo.toml b/Cargo.toml index 975fffc..4532d8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,3 +6,4 @@ edition = "2018" [dependencies] thiserror = "1.0.25" tiff = "0.7.0" +png = "0.16" diff --git a/src/codec.rs b/src/codec.rs index 55b77f2..ed576d9 100644 --- a/src/codec.rs +++ b/src/codec.rs @@ -137,12 +137,12 @@ mod tests { #[test] fn test_codec_12131() { - let frame = RGB48Frame::open("src/testdata/tears_of_steel_12130.tif").unwrap(); + let frame = RGB48Frame::from_tiff("src/testdata/tears_of_steel_12130.tif").unwrap(); assert_eq!(frame.data.len(), 4096 * 1714 * 3); // 42,123,264 bytes uncompressed let mut encoded = Vec::new(); frame.encode::(&mut encoded).unwrap(); - assert_eq!(encoded.len(), 25526583); + assert_eq!(encoded.len(), 25526584); let decoded = RGB48Frame::decode::(&*encoded, frame.width, frame.height).unwrap(); assert_eq!(frame == decoded, true); @@ -150,12 +150,12 @@ mod tests { #[test] fn test_codec_12209() { - let frame = RGB48Frame::open("src/testdata/tears_of_steel_12209.tif").unwrap(); + let frame = RGB48Frame::from_tiff("src/testdata/tears_of_steel_12209.tif").unwrap(); assert_eq!(frame.data.len(), 4096 * 1714 * 3); // 42,123,264 bytes uncompressed let mut encoded = Vec::new(); frame.encode::(&mut encoded).unwrap(); - assert_eq!(encoded.len(), 28270586); + assert_eq!(encoded.len(), 28270587); let decoded = RGB48Frame::decode::(&*encoded, frame.width, frame.height).unwrap(); assert_eq!(frame == decoded, true); diff --git a/src/frame.rs b/src/frame.rs index bd352cd..d6414be 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -2,6 +2,8 @@ use std::{ io::{self, Read, Write}, path::Path, }; + +use super::bitstream::{Bitstream, BitstreamWriter}; use thiserror::Error; pub struct Plane { @@ -29,6 +31,8 @@ pub enum FrameOpenError { IO(#[from] io::Error), #[error(transparent)] TiffError(#[from] tiff::TiffError), + #[error(transparent)] + PngError(#[from] png::DecodingError), #[error("unsupported color type: {0:?}")] UnsupportedColorType(tiff::ColorType), #[error("unsupported sample type")] @@ -43,7 +47,20 @@ pub struct RGB48Frame { } impl RGB48Frame { - pub fn open>(path: P) -> Result { + pub fn from_png>(path: P) -> Result { + let decoder = png::Decoder::new(std::fs::File::open(path)?); + let (info, mut reader) = decoder.read_info()?; + let mut data = vec![0; info.buffer_size()]; + reader.next_frame(&mut data)?; + let data = data.iter().map(|&x| x as u16).collect(); + Ok(RGB48Frame { + data, + width: info.width as _, + height: info.height as _, + }) + } + + pub fn from_tiff>(path: P) -> Result { let f = std::fs::File::open(path)?; let mut dec = tiff::decoder::Decoder::new(f)?.with_limits(tiff::decoder::Limits::unlimited()); @@ -63,32 +80,24 @@ impl RGB48Frame { } pub fn planes(&self) -> Vec> { - vec![ - Plane { - data: &self.data, - width: self.width, - height: self.height, - row_stride: 3 * self.width, - sample_stride: 3, - }, - Plane { - data: &self.data[1..], - width: self.width, - height: self.height, - row_stride: 3 * self.width, - sample_stride: 3, - }, - Plane { - data: &self.data[2..], + let n_planes = self.data.len() / (self.width * self.height); + return (0..n_planes) + .map(|plane| Plane { + data: &self.data[plane..], width: self.width, height: self.height, - row_stride: 3 * self.width, - sample_stride: 3, - }, - ] + row_stride: n_planes * self.width, + sample_stride: n_planes, + }) + .collect(); } pub fn encode(&self, mut dest: W) -> io::Result<()> { + { + let mut bitstream = BitstreamWriter::new(&mut dest); + bitstream.write_bits((self.planes().len() - 1) as _, 2)?; + bitstream.flush()?; + } for plane in self.planes() { C::encode(&plane, &mut dest)?; } @@ -100,20 +109,24 @@ impl RGB48Frame { width: usize, height: usize, ) -> io::Result { + let n_planes = { + let mut bitstream = Bitstream::new(&mut source); + (bitstream.read_bits(2)? as usize) + 1 + }; let mut ret = Self { - data: vec![0; width * height * 3], + data: vec![0; width * height * n_planes], width, height, }; - for plane in 0..3 { + for plane in 0..n_planes { C::decode( &mut source, &mut Plane { data: &mut ret.data[plane..], width: width, height: height, - row_stride: 3 * width, - sample_stride: 3, + row_stride: n_planes * width, + sample_stride: n_planes, }, )?; } @@ -127,6 +140,6 @@ mod tests { #[test] fn test_rgb48_frame_open() { - RGB48Frame::open("src/testdata/tears_of_steel_12130.tif").unwrap(); + RGB48Frame::from_tiff("src/testdata/tears_of_steel_12130.tif").unwrap(); } }