Add initial support for modern JPEG compression
Some things still need to be done: - Check RGB images - Check small images - Check huffman-only jpeg tables - Check empty jpeg tables - Add tests
This commit is contained in:
1 parent
da9bdac8a2
commit
2cb57a4d04
5 files changed
+184
-1
No files matched your search
@@ -187,6 +187,14 @@ pub trait EndianReader: Read {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// # READERS
|
||||
///
|
||||
|
||||
///
|
||||
/// ## Deflate Reader
|
||||
///
|
||||
|
||||
/// Reader that decompresses DEFLATE streams
|
||||
pub struct DeflateReader {
|
||||
buffer: io::Cursor<Vec<u8>>,
|
||||
@@ -233,6 +241,10 @@ impl EndianReader for DeflateReader {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// ## LZW Reader
|
||||
///
|
||||
|
||||
/// Reader that decompresses LZW streams
|
||||
pub struct LZWReader {
|
||||
buffer: io::Cursor<Vec<u8>>,
|
||||
@@ -306,6 +318,76 @@ impl EndianReader for LZWReader {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// ## JPEG Reader (for "new-style" JPEG format (TIFF compression tag 7))
|
||||
///
|
||||
|
||||
pub struct JpegReader {
|
||||
buffer: io::Cursor<Vec<u8>>,
|
||||
byte_order: ByteOrder, // for jpeg image data always ...,
|
||||
}
|
||||
// Only tested with qtables in jpegtables, but it contain both qtables and huffman tables or either
|
||||
impl JpegReader {
|
||||
/// Constructs new JpegReader wrapping a SmartReader.
|
||||
/// Because Jpeg compression in TIFF allows to save quantization and/or huffman tables in one
|
||||
/// central loacation, the constructor accepts this data as `jpeg_tables` here containing either
|
||||
/// both.
|
||||
/// These `jpeg_tables` are simply prepended to the remaining jpeg image data.
|
||||
/// Because these jpegtables start with a `SOI` (HEX: `0xFFD8`) or __start of image__ marker
|
||||
/// which is also at the beginning of the remaining jpeg image data and would
|
||||
/// confuse the jpeg renderer, one of these has to be taken off. In this case the first two
|
||||
/// bytes of the remaining jpeg data is removed because this follows `jpeg_tables`.
|
||||
/// Similary, `jpeg_tables` ends with a `EOI` (HEX: `0xFFD9`) or __end of image__ marker,
|
||||
/// this has to be removed as well (last two bytes of `jpeg_tables`).
|
||||
|
||||
pub fn new<R>(
|
||||
reader: &mut SmartReader<R>,
|
||||
length: u32,
|
||||
jpeg_tables: &Vec<u8>
|
||||
) -> io::Result<JpegReader>
|
||||
where
|
||||
R: Read + Seek,
|
||||
{
|
||||
let order = reader.byte_order;
|
||||
|
||||
// Read jpeg image data
|
||||
let mut segment = vec![0; length as usize];
|
||||
reader.read_exact(&mut segment[..])?;
|
||||
|
||||
let mut jpeg_data = jpeg_tables.clone();
|
||||
jpeg_data.truncate(jpeg_data.len() - 2);
|
||||
|
||||
jpeg_data.extend_from_slice(&mut segment[2..]);
|
||||
|
||||
Ok(
|
||||
JpegReader {
|
||||
buffer: io::Cursor::new(jpeg_data),
|
||||
byte_order: order,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for JpegReader {
|
||||
// #[inline]
|
||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||
self.buffer.read(buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl EndianReader for JpegReader {
|
||||
#[inline(always)]
|
||||
fn byte_order(&self) -> ByteOrder {
|
||||
self.byte_order
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// ## PackBits Reader
|
||||
///
|
||||
|
||||
/// Reader that unpacks Apple's `PackBits` format
|
||||
pub struct PackBitsReader {
|
||||
buffer: io::Cursor<Vec<u8>>,
|
||||
@@ -378,6 +460,10 @@ impl EndianReader for PackBitsReader {
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// ## SmartReader Reader
|
||||
///
|
||||
|
||||
/// Reader that is aware of the byte order.
|
||||
#[derive(Debug)]
|
||||
pub struct SmartReader<R>
|
||||
|
||||
Reference in new issue
Block a user