Support 64-bit grayscale decoding
This commit is contained in:
1 parent
af010edcfd
commit
f4e985e0bd
4 files changed
+78
-1
No files matched your search
+37
-1
@@ -21,6 +21,8 @@ pub enum DecodingResult {
|
||||
U16(Vec<u16>),
|
||||
/// A vector of 32 bit unsigned ints
|
||||
U32(Vec<u32>),
|
||||
/// A vector of 64 bit unsigned ints
|
||||
U64(Vec<u64>),
|
||||
}
|
||||
|
||||
impl DecodingResult {
|
||||
@@ -48,11 +50,20 @@ impl DecodingResult {
|
||||
}
|
||||
}
|
||||
|
||||
fn new_u64(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
|
||||
if size > limits.decoding_buffer_size / 8 {
|
||||
Err(TiffError::LimitsExceeded)
|
||||
} else {
|
||||
Ok(DecodingResult::U64(vec![0; size]))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_buffer(&mut self, start: usize) -> DecodingBuffer {
|
||||
match *self {
|
||||
DecodingResult::U8(ref mut buf) => DecodingBuffer::U8(&mut buf[start..]),
|
||||
DecodingResult::U16(ref mut buf) => DecodingBuffer::U16(&mut buf[start..]),
|
||||
DecodingResult::U32(ref mut buf) => DecodingBuffer::U32(&mut buf[start..]),
|
||||
DecodingResult::U64(ref mut buf) => DecodingBuffer::U64(&mut buf[start..]),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,6 +76,8 @@ pub enum DecodingBuffer<'a> {
|
||||
U16(&'a mut [u16]),
|
||||
/// A slice of 32 bit unsigned ints
|
||||
U32(&'a mut [u32]),
|
||||
/// A slice of 64 bit unsigned ints
|
||||
U64(&'a mut [u64]),
|
||||
}
|
||||
|
||||
impl<'a> DecodingBuffer<'a> {
|
||||
@@ -73,6 +86,7 @@ impl<'a> DecodingBuffer<'a> {
|
||||
DecodingBuffer::U8(ref buf) => buf.len(),
|
||||
DecodingBuffer::U16(ref buf) => buf.len(),
|
||||
DecodingBuffer::U32(ref buf) => buf.len(),
|
||||
DecodingBuffer::U64(ref buf) => buf.len(),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,6 +95,7 @@ impl<'a> DecodingBuffer<'a> {
|
||||
DecodingBuffer::U8(_) => 1,
|
||||
DecodingBuffer::U16(_) => 2,
|
||||
DecodingBuffer::U32(_) => 4,
|
||||
DecodingBuffer::U64(_) => 8,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +107,7 @@ impl<'a> DecodingBuffer<'a> {
|
||||
DecodingBuffer::U8(ref mut buf) => DecodingBuffer::U8(buf),
|
||||
DecodingBuffer::U16(ref mut buf) => DecodingBuffer::U16(buf),
|
||||
DecodingBuffer::U32(ref mut buf) => DecodingBuffer::U32(buf),
|
||||
DecodingBuffer::U64(ref mut buf) => DecodingBuffer::U64(buf),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -255,6 +271,12 @@ impl Wrapping for u32 {
|
||||
}
|
||||
}
|
||||
|
||||
impl Wrapping for u64 {
|
||||
fn wrapping_add(&self, other: Self) -> Self {
|
||||
u64::wrapping_add(*self, other)
|
||||
}
|
||||
}
|
||||
|
||||
fn rev_hpredict_nsamp<T>(image: &mut [T], size: (u32, u32), samples: usize)
|
||||
where
|
||||
T: Copy + Wrapping,
|
||||
@@ -272,7 +294,7 @@ where
|
||||
|
||||
fn rev_hpredict(image: DecodingBuffer, size: (u32, u32), color_type: ColorType) -> TiffResult<()> {
|
||||
let samples = match color_type {
|
||||
ColorType::Gray(8) | ColorType::Gray(16) | ColorType::Gray(32) => 1,
|
||||
ColorType::Gray(8) | ColorType::Gray(16) | ColorType::Gray(32) | ColorType::Gray(64) => 1,
|
||||
ColorType::RGB(8) | ColorType::RGB(16) | ColorType::RGB(32) => 3,
|
||||
ColorType::RGBA(8) | ColorType::RGBA(16) | ColorType::RGBA(32) | ColorType::CMYK(8) => 4,
|
||||
_ => {
|
||||
@@ -291,6 +313,9 @@ fn rev_hpredict(image: DecodingBuffer, size: (u32, u32), color_type: ColorType)
|
||||
DecodingBuffer::U32(buf) => {
|
||||
rev_hpredict_nsamp(buf, size, samples);
|
||||
}
|
||||
DecodingBuffer::U64(buf) => {
|
||||
rev_hpredict_nsamp(buf, size, samples);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -695,6 +720,15 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
reader.read_u32_into(&mut buffer[..bytes / 4])?;
|
||||
bytes / 4
|
||||
}
|
||||
(ColorType::Gray(64), DecodingBuffer::U64(ref mut buffer)) => {
|
||||
reader.read_u64_into(&mut buffer[..bytes / 8])?;
|
||||
if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
|
||||
for datum in buffer[..bytes / 8].iter_mut() {
|
||||
*datum = 0xffff_ffff_ffff_ffff - *datum
|
||||
}
|
||||
}
|
||||
bytes / 8
|
||||
}
|
||||
(ColorType::Gray(32), DecodingBuffer::U32(ref mut buffer)) => {
|
||||
reader.read_u32_into(&mut buffer[..bytes / 4])?;
|
||||
if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
|
||||
@@ -852,6 +886,7 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
n if n <= 8 => DecodingResult::new_u8(buffer_size, &self.limits)?,
|
||||
n if n <= 16 => DecodingResult::new_u16(buffer_size, &self.limits)?,
|
||||
n if n <= 32 => DecodingResult::new_u32(buffer_size, &self.limits)?,
|
||||
n if n <= 64 => DecodingResult::new_u64(buffer_size, &self.limits)?,
|
||||
n => {
|
||||
return Err(TiffError::UnsupportedError(
|
||||
TiffUnsupportedError::UnsupportedBitsPerChannel(n),
|
||||
@@ -881,6 +916,7 @@ impl<R: Read + Seek> Decoder<R> {
|
||||
n if n <= 8 => DecodingResult::new_u8(buffer_size, &self.limits)?,
|
||||
n if n <= 16 => DecodingResult::new_u16(buffer_size, &self.limits)?,
|
||||
n if n <= 32 => DecodingResult::new_u32(buffer_size, &self.limits)?,
|
||||
n if n <= 64 => DecodingResult::new_u64(buffer_size, &self.limits)?,
|
||||
n => {
|
||||
return Err(TiffError::UnsupportedError(
|
||||
TiffUnsupportedError::UnsupportedBitsPerChannel(n),
|
||||
|
||||
@@ -71,6 +71,27 @@ pub trait EndianReader: Read {
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads an u64
|
||||
#[inline(always)]
|
||||
fn read_u64(&mut self) -> Result<u64, io::Error> {
|
||||
match self.byte_order() {
|
||||
ByteOrder::LittleEndian => <Self as ReadBytesExt>::read_u64::<LittleEndian>(self),
|
||||
ByteOrder::BigEndian => <Self as ReadBytesExt>::read_u64::<BigEndian>(self),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn read_u64_into(&mut self, buffer: &mut [u64]) -> Result<(), io::Error> {
|
||||
match self.byte_order() {
|
||||
ByteOrder::LittleEndian => {
|
||||
<Self as ReadBytesExt>::read_u64_into::<LittleEndian>(self, buffer)
|
||||
}
|
||||
ByteOrder::BigEndian => {
|
||||
<Self as ReadBytesExt>::read_u64_into::<BigEndian>(self, buffer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads an i32
|
||||
#[inline(always)]
|
||||
fn read_i32(&mut self) -> Result<i32, io::Error> {
|
||||
|
||||
@@ -84,6 +84,26 @@ fn test_gray_u32() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_gray_u64() {
|
||||
let img_file =
|
||||
File::open("./tests/images/gradient-1c-64b.tiff").expect("Cannot find test image!");
|
||||
let mut decoder = Decoder::new(img_file).expect("Cannot create decoder");
|
||||
assert_eq!(decoder.colortype().unwrap(), ColorType::Gray(64));
|
||||
let img_res = decoder.read_image().unwrap();
|
||||
if let DecodingResult::U64(res) = img_res {
|
||||
let mut res_sum: u64 = 0;
|
||||
for x in res {
|
||||
res_sum += x as u64;
|
||||
}
|
||||
|
||||
assert_eq!(res_sum, 549892913787);
|
||||
}
|
||||
else {
|
||||
panic!("Wrong bit depth")
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rgb_u16() {
|
||||
let img_file = File::open("./tests/images/rgb-3c-16b.tiff").expect("Cannot find test image!");
|
||||
|
||||
Binary file not shown.
Reference in new issue
Block a user