Add support for IEEEFP Gray/RGB/RGBA/CMYK(64) decoding
This commit is contained in:
1 parent
97c888f166
commit
c2084835fa
5 files changed
+73
-4
No files matched your search
@@ -17,12 +17,12 @@ This table lists photometric interpretations and sample formats which are suppor
|
|||||||
|
|
||||||
| `PhotometricInterpretation` | UINT Format | IEEEFP Format |
|
| `PhotometricInterpretation` | UINT Format | IEEEFP Format |
|
||||||
|-|-|-|
|
|-|-|-|
|
||||||
| `WhiteIsZero` | Gray(8\|16\|32\|64) | Gray(32) |
|
| `WhiteIsZero` | Gray(8\|16\|32\|64) | Gray(32\|64) |
|
||||||
| `BlackIsZero` | Gray(8\|16\|32\|64) | Gray(32) |
|
| `BlackIsZero` | Gray(8\|16\|32\|64) | Gray(32\|64) |
|
||||||
| `RGB` | RGB(8\|16\|32\|64), RGBA(8\|16\|32\|64) | RGB(32), RGBA(32) |
|
| `RGB` | RGB(8\|16\|32\|64), RGBA(8\|16\|32\|64) | RGB(32\|64), RGBA(32\|64) |
|
||||||
| `RGBPalette` | | |
|
| `RGBPalette` | | |
|
||||||
| `Mask` | | |
|
| `Mask` | | |
|
||||||
| `CMYK` | CMYK(8\|16\|32\|64) | CMYK(32) |
|
| `CMYK` | CMYK(8\|16\|32\|64) | CMYK(32\|64) |
|
||||||
| `YCbCr` | | |
|
| `YCbCr` | | |
|
||||||
| `CIELab` | | |
|
| `CIELab` | | |
|
||||||
|
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ pub enum DecodingResult {
|
|||||||
U64(Vec<u64>),
|
U64(Vec<u64>),
|
||||||
/// A vector of 32 bit IEEE floats
|
/// A vector of 32 bit IEEE floats
|
||||||
F32(Vec<f32>),
|
F32(Vec<f32>),
|
||||||
|
/// A vector of 64 bit IEEE floats
|
||||||
|
F64(Vec<f64>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DecodingResult {
|
impl DecodingResult {
|
||||||
@@ -69,6 +71,14 @@ impl DecodingResult {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn new_f64(size: usize, limits: &Limits) -> TiffResult<DecodingResult> {
|
||||||
|
if size > limits.decoding_buffer_size / std::mem::size_of::<f64>() {
|
||||||
|
Err(TiffError::LimitsExceeded)
|
||||||
|
} else {
|
||||||
|
Ok(DecodingResult::F64(vec![0.0; size]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn as_buffer(&mut self, start: usize) -> DecodingBuffer {
|
pub fn as_buffer(&mut self, start: usize) -> DecodingBuffer {
|
||||||
match *self {
|
match *self {
|
||||||
DecodingResult::U8(ref mut buf) => DecodingBuffer::U8(&mut buf[start..]),
|
DecodingResult::U8(ref mut buf) => DecodingBuffer::U8(&mut buf[start..]),
|
||||||
@@ -76,6 +86,7 @@ impl DecodingResult {
|
|||||||
DecodingResult::U32(ref mut buf) => DecodingBuffer::U32(&mut buf[start..]),
|
DecodingResult::U32(ref mut buf) => DecodingBuffer::U32(&mut buf[start..]),
|
||||||
DecodingResult::U64(ref mut buf) => DecodingBuffer::U64(&mut buf[start..]),
|
DecodingResult::U64(ref mut buf) => DecodingBuffer::U64(&mut buf[start..]),
|
||||||
DecodingResult::F32(ref mut buf) => DecodingBuffer::F32(&mut buf[start..]),
|
DecodingResult::F32(ref mut buf) => DecodingBuffer::F32(&mut buf[start..]),
|
||||||
|
DecodingResult::F64(ref mut buf) => DecodingBuffer::F64(&mut buf[start..]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -92,6 +103,8 @@ pub enum DecodingBuffer<'a> {
|
|||||||
U64(&'a mut [u64]),
|
U64(&'a mut [u64]),
|
||||||
/// A slice of 32 bit IEEE floats
|
/// A slice of 32 bit IEEE floats
|
||||||
F32(&'a mut [f32]),
|
F32(&'a mut [f32]),
|
||||||
|
/// A slice of 64 bit IEEE floats
|
||||||
|
F64(&'a mut [f64]),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> DecodingBuffer<'a> {
|
impl<'a> DecodingBuffer<'a> {
|
||||||
@@ -102,6 +115,7 @@ impl<'a> DecodingBuffer<'a> {
|
|||||||
DecodingBuffer::U32(ref buf) => buf.len(),
|
DecodingBuffer::U32(ref buf) => buf.len(),
|
||||||
DecodingBuffer::U64(ref buf) => buf.len(),
|
DecodingBuffer::U64(ref buf) => buf.len(),
|
||||||
DecodingBuffer::F32(ref buf) => buf.len(),
|
DecodingBuffer::F32(ref buf) => buf.len(),
|
||||||
|
DecodingBuffer::F64(ref buf) => buf.len(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +126,7 @@ impl<'a> DecodingBuffer<'a> {
|
|||||||
DecodingBuffer::U32(_) => 4,
|
DecodingBuffer::U32(_) => 4,
|
||||||
DecodingBuffer::U64(_) => 8,
|
DecodingBuffer::U64(_) => 8,
|
||||||
DecodingBuffer::F32(_) => 4,
|
DecodingBuffer::F32(_) => 4,
|
||||||
|
DecodingBuffer::F64(_) => 8,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,6 +140,7 @@ impl<'a> DecodingBuffer<'a> {
|
|||||||
DecodingBuffer::U32(ref mut buf) => DecodingBuffer::U32(buf),
|
DecodingBuffer::U32(ref mut buf) => DecodingBuffer::U32(buf),
|
||||||
DecodingBuffer::U64(ref mut buf) => DecodingBuffer::U64(buf),
|
DecodingBuffer::U64(ref mut buf) => DecodingBuffer::U64(buf),
|
||||||
DecodingBuffer::F32(ref mut buf) => DecodingBuffer::F32(buf),
|
DecodingBuffer::F32(ref mut buf) => DecodingBuffer::F32(buf),
|
||||||
|
DecodingBuffer::F64(ref mut buf) => DecodingBuffer::F64(buf),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -220,6 +236,12 @@ impl Wrapping for f32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Wrapping for f64 {
|
||||||
|
fn wrapping_add(&self, other: Self) -> Self {
|
||||||
|
self + other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn rev_hpredict_nsamp<T>(image: &mut [T], size: (u32, u32), samples: usize) -> TiffResult<()>
|
fn rev_hpredict_nsamp<T>(image: &mut [T], size: (u32, u32), samples: usize) -> TiffResult<()>
|
||||||
where
|
where
|
||||||
T: Copy + Wrapping,
|
T: Copy + Wrapping,
|
||||||
@@ -264,6 +286,9 @@ fn rev_hpredict(image: DecodingBuffer, size: (u32, u32), color_type: ColorType)
|
|||||||
DecodingBuffer::F32(buf) => {
|
DecodingBuffer::F32(buf) => {
|
||||||
rev_hpredict_nsamp(buf, size, samples)?;
|
rev_hpredict_nsamp(buf, size, samples)?;
|
||||||
}
|
}
|
||||||
|
DecodingBuffer::F64(buf) => {
|
||||||
|
rev_hpredict_nsamp(buf, size, samples)?;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -678,6 +703,12 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
reader.read_f32_into(&mut buffer[..bytes / 4])?;
|
reader.read_f32_into(&mut buffer[..bytes / 4])?;
|
||||||
bytes / 4
|
bytes / 4
|
||||||
}
|
}
|
||||||
|
(ColorType::RGBA(64), DecodingBuffer::F64(ref mut buffer))
|
||||||
|
| (ColorType::RGB(64), DecodingBuffer::F64(ref mut buffer))
|
||||||
|
| (ColorType::CMYK(64), DecodingBuffer::F64(ref mut buffer)) => {
|
||||||
|
reader.read_f64_into(&mut buffer[..bytes / 8])?;
|
||||||
|
bytes / 8
|
||||||
|
}
|
||||||
(ColorType::RGBA(64), DecodingBuffer::U64(ref mut buffer))
|
(ColorType::RGBA(64), DecodingBuffer::U64(ref mut buffer))
|
||||||
| (ColorType::RGB(64), DecodingBuffer::U64(ref mut buffer))
|
| (ColorType::RGB(64), DecodingBuffer::U64(ref mut buffer))
|
||||||
| (ColorType::CMYK(64), DecodingBuffer::U64(ref mut buffer)) => {
|
| (ColorType::CMYK(64), DecodingBuffer::U64(ref mut buffer)) => {
|
||||||
@@ -730,6 +761,16 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
}
|
}
|
||||||
bytes / 4
|
bytes / 4
|
||||||
}
|
}
|
||||||
|
(ColorType::Gray(64), DecodingBuffer::F64(ref mut buffer)) => {
|
||||||
|
reader.read_f64_into(&mut buffer[..bytes / 8])?;
|
||||||
|
if self.photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
|
||||||
|
for datum in buffer[..bytes / 8].iter_mut() {
|
||||||
|
// FIXME: assumes [0, 1) range for floats
|
||||||
|
*datum = 1.0 - *datum
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bytes / 8
|
||||||
|
}
|
||||||
(type_, _) => {
|
(type_, _) => {
|
||||||
return Err(TiffError::UnsupportedError(
|
return Err(TiffError::UnsupportedError(
|
||||||
TiffUnsupportedError::UnsupportedColorType(type_),
|
TiffUnsupportedError::UnsupportedColorType(type_),
|
||||||
@@ -857,6 +898,7 @@ impl<R: Read + Seek> Decoder<R> {
|
|||||||
},
|
},
|
||||||
SampleFormat::IEEEFP => match max_sample_bits {
|
SampleFormat::IEEEFP => match max_sample_bits {
|
||||||
32 => DecodingResult::new_f32(buffer_size, &self.limits),
|
32 => DecodingResult::new_f32(buffer_size, &self.limits),
|
||||||
|
64 => DecodingResult::new_f64(buffer_size, &self.limits),
|
||||||
n => {
|
n => {
|
||||||
Err(TiffError::UnsupportedError(
|
Err(TiffError::UnsupportedError(
|
||||||
TiffUnsupportedError::UnsupportedBitsPerChannel(n),
|
TiffUnsupportedError::UnsupportedBitsPerChannel(n),
|
||||||
|
|||||||
@@ -121,6 +121,27 @@ pub trait EndianReader: Read {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Reads an f64
|
||||||
|
#[inline(always)]
|
||||||
|
fn read_f64(&mut self) -> Result<f64, io::Error> {
|
||||||
|
match self.byte_order() {
|
||||||
|
ByteOrder::LittleEndian => <Self as ReadBytesExt>::read_f64::<LittleEndian>(self),
|
||||||
|
ByteOrder::BigEndian => <Self as ReadBytesExt>::read_f64::<BigEndian>(self),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn read_f64_into(&mut self, buffer: &mut [f64]) -> Result<(), io::Error> {
|
||||||
|
match self.byte_order() {
|
||||||
|
ByteOrder::LittleEndian => {
|
||||||
|
<Self as ReadBytesExt>::read_f64_into::<LittleEndian>(self, buffer)
|
||||||
|
}
|
||||||
|
ByteOrder::BigEndian => {
|
||||||
|
<Self as ReadBytesExt>::read_f64_into::<BigEndian>(self, buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reader that decompresses DEFLATE streams
|
/// Reader that decompresses DEFLATE streams
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ test_image_sum!(test_image_sum_u16, U16, u64);
|
|||||||
test_image_sum!(test_image_sum_u32, U32, u64);
|
test_image_sum!(test_image_sum_u32, U32, u64);
|
||||||
test_image_sum!(test_image_sum_u64, U64, u64);
|
test_image_sum!(test_image_sum_u64, U64, u64);
|
||||||
test_image_sum!(test_image_sum_f32, F32, f32);
|
test_image_sum!(test_image_sum_f32, F32, f32);
|
||||||
|
test_image_sum!(test_image_sum_f64, F64, f64);
|
||||||
|
|
||||||
/// Tests that a decoder can be constructed for an image and the color type
|
/// Tests that a decoder can be constructed for an image and the color type
|
||||||
/// read from the IFD and is of the appropriate type, but the type is
|
/// read from the IFD and is of the appropriate type, but the type is
|
||||||
@@ -93,6 +94,11 @@ fn test_gray_f32() {
|
|||||||
test_image_sum_f32("gradient-1c-32b-float.tiff", ColorType::Gray(32), 128.03194);
|
test_image_sum_f32("gradient-1c-32b-float.tiff", ColorType::Gray(32), 128.03194);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_gray_f64() {
|
||||||
|
test_image_sum_f64("gradient-1c-64b-float.tiff", ColorType::Gray(64), 128.0319210877642);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_rgb_u8() {
|
fn test_rgb_u8() {
|
||||||
test_image_sum_u8("rgb-3c-8b.tiff", ColorType::RGB(8), 7842108);
|
test_image_sum_u8("rgb-3c-8b.tiff", ColorType::RGB(8), 7842108);
|
||||||
|
|||||||
Binary file not shown.
Reference in new issue
Block a user