Support floating point predictor (predictor 3)

Based on work by @TomasKralCZ in #135
This commit is contained in:
Jonathan Behrens committed 2022-06-22 20:14:25 -07:00
1 parent 8a6e93f66e
commit 8e5c5b44c5
7 files changed
+86 -1

No files matched your search

+31 -1
View File
@@ -4,8 +4,8 @@ use super::stream::{
PackBitsReader,
};
use super::tag_reader::TagReader;
use super::{fp_predict_f32, fp_predict_f64, DecodingBuffer, Limits};
use super::{stream::SmartReader, ChunkType};
use super::{DecodingBuffer, Limits};
use crate::tags::{CompressionMethod, PhotometricInterpretation, Predictor, SampleFormat, Tag};
use crate::{ColorType, TiffError, TiffFormatError, TiffResult, TiffUnsupportedError};
use std::convert::{TryFrom, TryInto};
@@ -406,6 +406,11 @@ impl Image {
TiffUnsupportedError::HorizontalPredictor(color_type),
))
}
Predictor::FloatingPoint => {
return Err(TiffError::UnsupportedError(
TiffUnsupportedError::FloatingPointPredictor(color_type),
));
}
Predictor::__NonExhaustive => unreachable!(),
},
(type_, _) => {
@@ -423,6 +428,13 @@ impl Image {
TiffUnsupportedError::HorizontalPredictor(color_type),
));
}
(Predictor::FloatingPoint, DecodingBuffer::F32(_))
| (Predictor::FloatingPoint, DecodingBuffer::F64(_)) => {}
(Predictor::FloatingPoint, _) => {
return Err(TiffError::UnsupportedError(
TiffUnsupportedError::FloatingPointPredictor(color_type),
));
}
_ => {}
}
@@ -471,6 +483,24 @@ impl Image {
if photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
super::invert_colors(&mut buffer.subrange(0..total_samples), color_type);
}
} else if padding.0 > 0 && self.predictor == Predictor::FloatingPoint {
// The floating point predictor shuffles the padding bytes into the encoded output, so
// this case is handled specially when needed.
for row in 0..(chunk_dimensions.1 - padding.1) {
let row_start = row * output_width * samples;
let row_end = row_start + (chunk_dimensions.0 - padding.0) * samples;
let mut encoded = vec![0u8; chunk_dimensions.0 * samples * byte_len];
reader.read_exact(&mut encoded)?;
match buffer.subrange(row_start..row_end) {
DecodingBuffer::F32(buf) => fp_predict_f32(&mut encoded, buf, samples),
DecodingBuffer::F64(buf) => fp_predict_f64(&mut encoded, buf, samples),
_ => unreachable!(),
}
if photometric_interpretation == PhotometricInterpretation::WhiteIsZero {
super::invert_colors(&mut buffer.subrange(row_start..row_end), color_type);
}
}
} else {
for row in 0..(chunk_dimensions.1 - padding.1) {
let row_start = row * output_width * samples;