Skip to content

Commit a0ff033

Browse files
committed
added planar_configuration back, updated bits_per_pixel and added tests
1 parent be74506 commit a0ff033

File tree

1 file changed

+66
-26
lines changed

1 file changed

+66
-26
lines changed

src/predictor.rs

Lines changed: 66 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use std::fmt::Debug;
44
use bytes::{Bytes, BytesMut};
55

66
use crate::error::AsyncTiffError;
7+
use crate::tiff::tags::PlanarConfiguration;
78
use crate::ImageFileDirectory;
89
use crate::{error::AsyncTiffResult, reader::Endianness};
910

@@ -34,6 +35,8 @@ pub(crate) struct PredictorInfo {
3435
bits_per_sample: u16,
3536
/// number of samples per pixel
3637
samples_per_pixel: u16,
38+
39+
planar_configuration: PlanarConfiguration,
3740
}
3841

3942
impl PredictorInfo {
@@ -60,15 +63,7 @@ impl PredictorInfo {
6063
image_height: ifd.image_height,
6164
chunk_width,
6265
chunk_height,
63-
// TODO: validate this? Restore handling for different PlanarConfiguration?
64-
// PlanarConfiguration::Chunky => {
65-
// if self.bits_per_sample.len() == 1 {
66-
// self.samples_per_pixel as usize * self.bits_per_sample[0] as usize
67-
// } else {
68-
// assert_eq!(self.samples_per_pixel as usize, self.bits_per_sample.len());
69-
// self.bits_per_sample.iter().map(|v| *v as usize).product()
70-
// }
71-
// }
66+
planar_configuration: ifd.planar_configuration,
7267
bits_per_sample: ifd.bits_per_sample[0],
7368
samples_per_pixel: ifd.samples_per_pixel,
7469
}
@@ -106,7 +101,27 @@ impl PredictorInfo {
106101

107102
/// get the output row stride in bytes, taking padding into account
108103
fn output_row_stride(&self, x: u32) -> AsyncTiffResult<usize> {
109-
Ok((self.chunk_width_pixels(x)? as usize).saturating_mul(self.bits_per_sample as _) / 8)
104+
Ok((self.chunk_width_pixels(x)? as usize).saturating_mul(self.bits_per_pixel()) / 8)
105+
}
106+
107+
/// the number of rows the output has, taking padding and PlanarConfiguration into account.
108+
fn output_rows(&self, y: u32) -> AsyncTiffResult<usize> {
109+
match self.planar_configuration {
110+
PlanarConfiguration::Chunky => Ok(self.chunk_height_pixels(y)? as usize),
111+
PlanarConfiguration::Planar => {
112+
Ok((self.chunk_height_pixels(y)? as usize)
113+
.saturating_mul(self.samples_per_pixel as _))
114+
}
115+
}
116+
}
117+
118+
fn bits_per_pixel(&self) -> usize {
119+
match self.planar_configuration {
120+
PlanarConfiguration::Chunky => {
121+
self.bits_per_sample as usize * self.samples_per_pixel as usize
122+
}
123+
PlanarConfiguration::Planar => self.bits_per_sample as usize,
124+
}
110125
}
111126

112127
/// The number of chunks in the horizontal (x) direction
@@ -275,9 +290,8 @@ impl Unpredict for FloatingPointPredictor {
275290
tile_y: u32,
276291
) -> AsyncTiffResult<Bytes> {
277292
let output_row_stride = predictor_info.output_row_stride(tile_x)?;
278-
let mut res: BytesMut = BytesMut::zeroed(
279-
output_row_stride * predictor_info.chunk_height_pixels(tile_y)? as usize,
280-
);
293+
let mut res: BytesMut =
294+
BytesMut::zeroed(output_row_stride * predictor_info.output_rows(tile_y)? as usize);
281295
let bit_depth = predictor_info.bits_per_sample;
282296
if predictor_info.chunk_width_pixels(tile_x)? == predictor_info.chunk_width {
283297
// no special padding handling
@@ -420,6 +434,7 @@ mod test {
420434
chunk_height: 4,
421435
bits_per_sample: 8,
422436
samples_per_pixel: 1,
437+
planar_configuration: PlanarConfiguration::Chunky,
423438
};
424439
#[rustfmt::skip]
425440
const RES: [u8;16] = [
@@ -454,23 +469,44 @@ mod test {
454469

455470
#[test]
456471
fn test_chunk_width_pixels() {
457-
let info = PredictorInfo {
458-
endianness: Endianness::LittleEndian,
459-
image_width: 15,
460-
image_height: 17,
461-
chunk_width: 8,
462-
chunk_height: 8,
463-
bits_per_sample: 8,
464-
samples_per_pixel: 1,
465-
};
472+
let info = PRED_INFO;
466473
assert_eq!(info.chunks_across(), 2);
467-
assert_eq!(info.chunks_down(), 3);
474+
assert_eq!(info.chunks_down(), 2);
468475
assert_eq!(info.chunk_width_pixels(0).unwrap(), info.chunk_width);
469-
assert_eq!(info.chunk_width_pixels(1).unwrap(), 7);
476+
assert_eq!(info.chunk_width_pixels(1).unwrap(), 3);
470477
info.chunk_width_pixels(2).unwrap_err();
471478
assert_eq!(info.chunk_height_pixels(0).unwrap(), info.chunk_height);
472-
assert_eq!(info.chunk_height_pixels(2).unwrap(), 1);
473-
info.chunk_height_pixels(3).unwrap_err();
479+
assert_eq!(info.chunk_height_pixels(1).unwrap(), 3);
480+
info.chunk_height_pixels(2).unwrap_err();
481+
}
482+
483+
#[test]
484+
fn test_output_row_stride() {
485+
let mut info = PRED_INFO;
486+
assert_eq!(info.output_row_stride(0).unwrap(), 4);
487+
assert_eq!(info.output_row_stride(1).unwrap(), 3);
488+
info.output_row_stride(2).unwrap_err();
489+
info.samples_per_pixel = 2;
490+
assert_eq!(info.output_row_stride(0).unwrap(), 8);
491+
assert_eq!(info.output_row_stride(1).unwrap(), 6);
492+
info.bits_per_sample = 16;
493+
assert_eq!(info.output_row_stride(0).unwrap(), 16);
494+
assert_eq!(info.output_row_stride(1).unwrap(), 12);
495+
info.planar_configuration = PlanarConfiguration::Planar;
496+
assert_eq!(info.output_row_stride(0).unwrap(), 8);
497+
assert_eq!(info.output_row_stride(1).unwrap(), 6);
498+
}
499+
500+
#[test]
501+
fn test_output_rows() {
502+
let mut info = PRED_INFO;
503+
info.samples_per_pixel = 2;
504+
assert_eq!(info.output_rows(0).unwrap(), 4);
505+
assert_eq!(info.output_rows(1).unwrap(), 3);
506+
info.output_rows(2).unwrap_err();
507+
info.planar_configuration = PlanarConfiguration::Planar;
508+
assert_eq!(info.output_rows(0).unwrap(), 8);
509+
assert_eq!(info.output_rows(1).unwrap(), 6);
474510
}
475511

476512
#[rustfmt::skip]
@@ -644,6 +680,7 @@ mod test {
644680
chunk_height: 4,
645681
bits_per_sample: 16,
646682
samples_per_pixel: 1,
683+
planar_configuration: PlanarConfiguration::Chunky,
647684
};
648685
let input = Bytes::from_owner(diffed);
649686
assert_eq!(
@@ -672,6 +709,7 @@ mod test {
672709
chunk_height: 4,
673710
bits_per_sample: 16,
674711
samples_per_pixel: 1,
712+
planar_configuration: PlanarConfiguration::Chunky,
675713
};
676714
let input = Bytes::from_owner(diffed);
677715
assert_eq!(
@@ -699,6 +737,7 @@ mod test {
699737
chunk_height: 2,
700738
bits_per_sample: 32,
701739
samples_per_pixel: 1,
740+
planar_configuration: PlanarConfiguration::Chunky,
702741
};
703742
let input = Bytes::from_owner(diffed);
704743
assert_eq!(
@@ -732,6 +771,7 @@ mod test {
732771
chunk_height: 2,
733772
bits_per_sample: 64,
734773
samples_per_pixel: 1,
774+
planar_configuration: PlanarConfiguration::Chunky,
735775
};
736776
let input = Bytes::from_owner(diffed);
737777
assert_eq!(

0 commit comments

Comments
 (0)