Refactor Group4 reader into stream module
This commit is contained in:
1 parent
c75aa98ce2
commit
80ce77190e
5 files changed
+74
-67
No files matched your search
+1
-1
@@ -20,7 +20,7 @@ exclude = ["tests/images/*", "tests/fuzz_images/*"]
|
|||||||
half = { version = "2.4.1" }
|
half = { version = "2.4.1" }
|
||||||
quick-error = "2.0.1"
|
quick-error = "2.0.1"
|
||||||
|
|
||||||
fax = { version = "0.2.2", optional = true }
|
fax = { version = "0.2.4", optional = true }
|
||||||
flate2 = { version = "1.0.20", optional = true }
|
flate2 = { version = "1.0.20", optional = true }
|
||||||
weezl = { version = "0.1.10", optional = true }
|
weezl = { version = "0.1.10", optional = true }
|
||||||
zstd = { version = "0.13", optional = true }
|
zstd = { version = "0.13", optional = true }
|
||||||
|
|||||||
+5
-64
@@ -10,8 +10,6 @@ use crate::{
|
|||||||
ColorType, Directory, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError, UsageError,
|
ColorType, Directory, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError, UsageError,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "fax")]
|
|
||||||
use std::collections::VecDeque;
|
|
||||||
use std::io::{self, Cursor, Read, Seek};
|
use std::io::{self, Cursor, Read, Seek};
|
||||||
use std::num::NonZeroUsize;
|
use std::num::NonZeroUsize;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@@ -458,68 +456,11 @@ impl Image {
|
|||||||
Box::new(Cursor::new(data))
|
Box::new(Cursor::new(data))
|
||||||
}
|
}
|
||||||
#[cfg(feature = "fax")]
|
#[cfg(feature = "fax")]
|
||||||
CompressionMethod::Fax4 => {
|
CompressionMethod::Fax4 => Box::new(super::stream::Group4Reader::new(
|
||||||
let width = u16::try_from(dimensions.0)?;
|
dimensions,
|
||||||
let height = u16::try_from(dimensions.1)?;
|
reader,
|
||||||
|
compressed_length,
|
||||||
struct Group4Reader<R2> {
|
)?),
|
||||||
decoder: fax::decoder::Group4Decoder<std::io::Bytes<R2>>,
|
|
||||||
bits: bitvec::vec::BitVec<u8, bitvec::prelude::Msb0>,
|
|
||||||
byte_buf: VecDeque<u8>,
|
|
||||||
y: u16,
|
|
||||||
height: u16,
|
|
||||||
width: u16,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R2: Read> Read for Group4Reader<R2> {
|
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
|
||||||
if self.byte_buf.is_empty() && self.y < self.height {
|
|
||||||
let next = self
|
|
||||||
.decoder
|
|
||||||
.advance()
|
|
||||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
|
|
||||||
|
|
||||||
match next {
|
|
||||||
fax::decoder::DecodeStatus::End => {
|
|
||||||
// eprintln!("DONE!");
|
|
||||||
self.byte_buf.extend(self.bits.as_raw_slice())
|
|
||||||
}
|
|
||||||
fax::decoder::DecodeStatus::Incomplete => {
|
|
||||||
self.y += 1;
|
|
||||||
// eprintln!("{:?}", self.y);
|
|
||||||
for c in
|
|
||||||
fax::decoder::pels(self.decoder.transition(), self.width)
|
|
||||||
{
|
|
||||||
self.bits.push(match c {
|
|
||||||
fax::Color::Black => true,
|
|
||||||
fax::Color::White => false,
|
|
||||||
});
|
|
||||||
if self.bits.len() == 8 {
|
|
||||||
self.byte_buf.extend(self.bits.as_raw_slice());
|
|
||||||
self.bits.clear()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// eprintln!("{:?}: {:?} / {:?}", self.y, self.byte_buf.len(), self.bits.len());
|
|
||||||
|
|
||||||
self.byte_buf.read(buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Box::new(Group4Reader {
|
|
||||||
decoder: fax::decoder::Group4Decoder::new(
|
|
||||||
reader.take(compressed_length).bytes(),
|
|
||||||
width,
|
|
||||||
)?,
|
|
||||||
bits: bitvec::vec::BitVec::new(),
|
|
||||||
byte_buf: VecDeque::new(),
|
|
||||||
y: 0,
|
|
||||||
width: width,
|
|
||||||
height: height,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
method => {
|
method => {
|
||||||
return Err(TiffError::UnsupportedError(
|
return Err(TiffError::UnsupportedError(
|
||||||
TiffUnsupportedError::UnsupportedCompressionMethod(method),
|
TiffUnsupportedError::UnsupportedCompressionMethod(method),
|
||||||
|
|||||||
@@ -547,7 +547,6 @@ fn fix_endianness(buf: &mut [u8], byte_order: ByteOrder, bit_depth: u8) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<R: Read + Seek> Decoder<R> {
|
impl<R: Read + Seek> Decoder<R> {
|
||||||
/// Create a new decoder that decodes from the stream ```r```
|
|
||||||
pub fn new(mut r: R) -> TiffResult<Decoder<R>> {
|
pub fn new(mut r: R) -> TiffResult<Decoder<R>> {
|
||||||
let mut endianess = Vec::with_capacity(2);
|
let mut endianess = Vec::with_capacity(2);
|
||||||
(&mut r).take(2).read_to_end(&mut endianess)?;
|
(&mut r).take(2).read_to_end(&mut endianess)?;
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
//! All IO functionality needed for TIFF decoding
|
//! All IO functionality needed for TIFF decoding
|
||||||
|
|
||||||
|
#[cfg(feature = "fax")]
|
||||||
|
use std::collections::VecDeque;
|
||||||
use std::io::{self, BufRead, BufReader, Read, Seek, Take};
|
use std::io::{self, BufRead, BufReader, Read, Seek, Take};
|
||||||
|
|
||||||
/// Byte order of the TIFF file.
|
/// Byte order of the TIFF file.
|
||||||
@@ -276,6 +278,71 @@ impl<R: Read> Read for PackBitsReader<R> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "fax")]
|
||||||
|
pub struct Group4Reader<R: Read> {
|
||||||
|
decoder: fax::decoder::Group4Decoder<io::Bytes<io::Take<R>>>,
|
||||||
|
bits: bitvec::vec::BitVec<u8, bitvec::prelude::Msb0>,
|
||||||
|
byte_buf: VecDeque<u8>,
|
||||||
|
height: u16,
|
||||||
|
width: u16,
|
||||||
|
y: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "fax")]
|
||||||
|
impl<R: Read> Group4Reader<R> {
|
||||||
|
pub fn new(
|
||||||
|
dimensions: (u32, u32),
|
||||||
|
reader: R,
|
||||||
|
compressed_length: u64,
|
||||||
|
) -> crate::TiffResult<Self> {
|
||||||
|
let width = u16::try_from(dimensions.0)?;
|
||||||
|
let height = u16::try_from(dimensions.1)?;
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
decoder: fax::decoder::Group4Decoder::new(
|
||||||
|
reader.take(compressed_length).bytes(),
|
||||||
|
width,
|
||||||
|
)?,
|
||||||
|
bits: bitvec::vec::BitVec::new(),
|
||||||
|
byte_buf: VecDeque::new(),
|
||||||
|
width: width,
|
||||||
|
height: height,
|
||||||
|
y: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dump_bits(&mut self) -> () {
|
||||||
|
self.byte_buf.extend(self.bits.as_raw_slice());
|
||||||
|
self.bits.clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "fax")]
|
||||||
|
impl<R: Read> Read for Group4Reader<R> {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
if self.byte_buf.is_empty() && self.y < self.height {
|
||||||
|
let next = self
|
||||||
|
.decoder
|
||||||
|
.advance()
|
||||||
|
.map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, e))?;
|
||||||
|
match next {
|
||||||
|
fax::decoder::DecodeStatus::End => self.dump_bits(),
|
||||||
|
fax::decoder::DecodeStatus::Incomplete => {
|
||||||
|
self.y += 1;
|
||||||
|
for c in fax::decoder::pels(self.decoder.transition(), self.width) {
|
||||||
|
self.bits.push(match c {
|
||||||
|
fax::Color::Black => true,
|
||||||
|
fax::Color::White => false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
self.dump_bits();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
self.byte_buf.read(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|||||||
@@ -676,5 +676,5 @@ fn bytes_gray_f32() {
|
|||||||
#[test]
|
#[test]
|
||||||
#[cfg(feature = "fax")]
|
#[cfg(feature = "fax")]
|
||||||
fn test_fax4() {
|
fn test_fax4() {
|
||||||
test_image_sum_u8("fax4.tiff", ColorType::Gray(1), 62384985);
|
test_image_sum_u8("fax4.tiff", ColorType::Gray(1), 7802706);
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user