Merge fix_endianness and rev_hpredict methods

This commit is contained in:
Jonathan Behrens committed 2022-06-22 20:13:55 -07:00
1 parent 68d677d1b3
commit 8a6e93f66e
2 files changed
+55 -103

No files matched your search

+29 -20
View File
@@ -399,7 +399,15 @@ impl Image {
| (ColorType::CMYK(n), _) | (ColorType::CMYK(n), _)
| (ColorType::Gray(n), _) | (ColorType::Gray(n), _)
if usize::from(n) == buffer.byte_len() * 8 => {} if usize::from(n) == buffer.byte_len() * 8 => {}
(ColorType::Gray(n), DecodingBuffer::U8(_)) if n <= 8 => {} (ColorType::Gray(n), DecodingBuffer::U8(_)) if n < 8 => match self.predictor {
Predictor::None => {}
Predictor::Horizontal => {
return Err(TiffError::UnsupportedError(
TiffUnsupportedError::HorizontalPredictor(color_type),
))
}
Predictor::__NonExhaustive => unreachable!(),
},
(type_, _) => { (type_, _) => {
return Err(TiffError::UnsupportedError( return Err(TiffError::UnsupportedError(
TiffUnsupportedError::UnsupportedColorType(type_), TiffUnsupportedError::UnsupportedColorType(type_),
@@ -407,6 +415,17 @@ impl Image {
} }
} }
// Validate that the predictor is supported for the sample type.
match (self.predictor, &buffer) {
(Predictor::Horizontal, DecodingBuffer::F32(_))
| (Predictor::Horizontal, DecodingBuffer::F64(_)) => {
return Err(TiffError::UnsupportedError(
TiffUnsupportedError::HorizontalPredictor(color_type),
));
}
_ => {}
}
let compressed_bytes = self.chunk_bytes.get(chunk).ok_or(TiffError::FormatError( let compressed_bytes = self.chunk_bytes.get(chunk).ok_or(TiffError::FormatError(
TiffFormatError::InconsistentSizesEncountered, TiffFormatError::InconsistentSizesEncountered,
))?; ))?;
@@ -443,7 +462,12 @@ impl Image {
let tile = &mut buffer.as_bytes_mut()[..total_samples * byte_len]; let tile = &mut buffer.as_bytes_mut()[..total_samples * byte_len];
reader.read_exact(tile)?; reader.read_exact(tile)?;
super::fix_endianness(&mut buffer.subrange(0..total_samples), byte_order); for row in 0..(chunk_dimensions.1 - padding.1) {
let row_start = row * output_width * samples;
let row_end = (row + 1) * output_width * samples;
let row = buffer.subrange(row_start..row_end);
super::fix_endianness_and_predict(row, samples, byte_order, predictor);
}
if photometric_interpretation == PhotometricInterpretation::WhiteIsZero { if photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
super::invert_colors(&mut buffer.subrange(0..total_samples), color_type); super::invert_colors(&mut buffer.subrange(0..total_samples), color_type);
} }
@@ -461,29 +485,14 @@ impl Image {
io::copy(&mut reader.by_ref().take(len), &mut io::sink())?; io::copy(&mut reader.by_ref().take(len), &mut io::sink())?;
} }
super::fix_endianness(&mut buffer.subrange(row_start..row_end), byte_order); let mut row = buffer.subrange(row_start..row_end);
super::fix_endianness_and_predict(row.copy(), samples, byte_order, predictor);
if photometric_interpretation == PhotometricInterpretation::WhiteIsZero { if photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
super::invert_colors(&mut buffer.subrange(row_start..row_end), color_type); super::invert_colors(&mut row, color_type);
} }
} }
} }
match predictor {
Predictor::None => {}
Predictor::Horizontal => {
super::rev_hpredict(
buffer,
(
u32::try_from(chunk_dimensions.0 - padding.0)?,
u32::try_from(chunk_dimensions.1 - padding.1)?,
),
output_width,
color_type,
)?;
}
Predictor::__NonExhaustive => unreachable!(),
}
Ok(()) Ok(())
} }
} }
+26 -83
View File
@@ -359,95 +359,38 @@ impl Wrapping for i64 {
} }
} }
fn rev_hpredict_nsamp<T>( fn rev_hpredict_nsamp<T: Copy + Wrapping>(image: &mut [T], samples: usize) {
image: &mut [T], for col in samples..image.len() {
size: (u32, u32), // Size of the block image[col] = image[col].wrapping_add(image[col - samples]);
img_width: usize, // Width of the image (this distinction is needed for tiles)
samples: usize,
) -> TiffResult<()>
where
T: Copy + Wrapping,
{
let width = usize::try_from(size.0)?;
let height = usize::try_from(size.1)?;
for row in 0..height {
for col in samples..width * samples {
let prev_pixel = image[(row * img_width * samples + col - samples)];
let pixel = &mut image[(row * img_width * samples + col)];
*pixel = pixel.wrapping_add(prev_pixel);
}
} }
Ok(())
} }
fn rev_hpredict( fn fix_endianness_and_predict(
image: DecodingBuffer, mut image: DecodingBuffer,
size: (u32, u32), samples: usize,
img_width: usize, byte_order: ByteOrder,
color_type: ColorType, predictor: Predictor,
) -> TiffResult<()> { ) {
// TODO: use bits_per_sample.len() after implementing type 3 predictor match predictor {
let samples = match color_type { Predictor::None => {
ColorType::Gray(8) | ColorType::Gray(16) | ColorType::Gray(32) | ColorType::Gray(64) => 1, fix_endianness(&mut image, byte_order);
ColorType::RGB(8) | ColorType::RGB(16) | ColorType::RGB(32) | ColorType::RGB(64) => 3,
ColorType::RGBA(8)
| ColorType::RGBA(16)
| ColorType::RGBA(32)
| ColorType::RGBA(64)
| ColorType::CMYK(8)
| ColorType::CMYK(16)
| ColorType::CMYK(32)
| ColorType::CMYK(64) => 4,
_ => {
return Err(TiffError::UnsupportedError(
TiffUnsupportedError::HorizontalPredictor(color_type),
))
} }
}; Predictor::Horizontal => {
fix_endianness(&mut image, byte_order);
match image { match image {
DecodingBuffer::U8(buf) => { DecodingBuffer::U8(buf) => rev_hpredict_nsamp(buf, samples),
rev_hpredict_nsamp(buf, size, img_width, samples)?; DecodingBuffer::U16(buf) => rev_hpredict_nsamp(buf, samples),
} DecodingBuffer::U32(buf) => rev_hpredict_nsamp(buf, samples),
DecodingBuffer::U16(buf) => { DecodingBuffer::U64(buf) => rev_hpredict_nsamp(buf, samples),
rev_hpredict_nsamp(buf, size, img_width, samples)?; DecodingBuffer::I8(buf) => rev_hpredict_nsamp(buf, samples),
} DecodingBuffer::I16(buf) => rev_hpredict_nsamp(buf, samples),
DecodingBuffer::U32(buf) => { DecodingBuffer::I32(buf) => rev_hpredict_nsamp(buf, samples),
rev_hpredict_nsamp(buf, size, img_width, samples)?; DecodingBuffer::I64(buf) => rev_hpredict_nsamp(buf, samples),
} DecodingBuffer::F32(_) | DecodingBuffer::F64(_) => unreachable!(),
DecodingBuffer::U64(buf) => { }
rev_hpredict_nsamp(buf, size, img_width, samples)?;
}
DecodingBuffer::F32(_buf) => {
// FIXME: check how this is defined.
// See issue #89.
// rev_hpredict_nsamp(buf, size, img_width,samples)?;
return Err(TiffError::UnsupportedError(
TiffUnsupportedError::HorizontalPredictor(color_type),
));
}
DecodingBuffer::F64(_buf) => {
//FIXME: check how this is defined.
// See issue #89.
// rev_hpredict_nsamp(buf, size, img_width,samples)?;
return Err(TiffError::UnsupportedError(
TiffUnsupportedError::HorizontalPredictor(color_type),
));
}
DecodingBuffer::I8(buf) => {
rev_hpredict_nsamp(buf, size, img_width, samples)?;
}
DecodingBuffer::I16(buf) => {
rev_hpredict_nsamp(buf, size, img_width, samples)?;
}
DecodingBuffer::I32(buf) => {
rev_hpredict_nsamp(buf, size, img_width, samples)?;
}
DecodingBuffer::I64(buf) => {
rev_hpredict_nsamp(buf, size, img_width, samples)?;
} }
Predictor::__NonExhaustive => unreachable!(),
} }
Ok(())
} }
fn invert_colors_unsigned<T>(buffer: &mut [T], max: T) fn invert_colors_unsigned<T>(buffer: &mut [T], max: T)