@@ -4,6 +4,7 @@ use std::fmt::Debug;
4
4
use bytes:: { Bytes , BytesMut } ;
5
5
6
6
use crate :: error:: AsyncTiffError ;
7
+ use crate :: tiff:: tags:: PlanarConfiguration ;
7
8
use crate :: ImageFileDirectory ;
8
9
use crate :: { error:: AsyncTiffResult , reader:: Endianness } ;
9
10
@@ -34,6 +35,8 @@ pub(crate) struct PredictorInfo {
34
35
bits_per_sample : u16 ,
35
36
/// number of samples per pixel
36
37
samples_per_pixel : u16 ,
38
+
39
+ planar_configuration : PlanarConfiguration ,
37
40
}
38
41
39
42
impl PredictorInfo {
@@ -60,15 +63,7 @@ impl PredictorInfo {
60
63
image_height : ifd. image_height ,
61
64
chunk_width,
62
65
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 ,
72
67
bits_per_sample : ifd. bits_per_sample [ 0 ] ,
73
68
samples_per_pixel : ifd. samples_per_pixel ,
74
69
}
@@ -106,7 +101,27 @@ impl PredictorInfo {
106
101
107
102
/// get the output row stride in bytes, taking padding into account
108
103
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
+ }
110
125
}
111
126
112
127
/// The number of chunks in the horizontal (x) direction
@@ -275,9 +290,8 @@ impl Unpredict for FloatingPointPredictor {
275
290
tile_y : u32 ,
276
291
) -> AsyncTiffResult < Bytes > {
277
292
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 ) ;
281
295
let bit_depth = predictor_info. bits_per_sample ;
282
296
if predictor_info. chunk_width_pixels ( tile_x) ? == predictor_info. chunk_width {
283
297
// no special padding handling
@@ -420,6 +434,7 @@ mod test {
420
434
chunk_height : 4 ,
421
435
bits_per_sample : 8 ,
422
436
samples_per_pixel : 1 ,
437
+ planar_configuration : PlanarConfiguration :: Chunky ,
423
438
} ;
424
439
#[ rustfmt:: skip]
425
440
const RES : [ u8 ; 16 ] = [
@@ -454,23 +469,44 @@ mod test {
454
469
455
470
#[ test]
456
471
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 ;
466
473
assert_eq ! ( info. chunks_across( ) , 2 ) ;
467
- assert_eq ! ( info. chunks_down( ) , 3 ) ;
474
+ assert_eq ! ( info. chunks_down( ) , 2 ) ;
468
475
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 ) ;
470
477
info. chunk_width_pixels ( 2 ) . unwrap_err ( ) ;
471
478
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 ) ;
474
510
}
475
511
476
512
#[ rustfmt:: skip]
@@ -644,6 +680,7 @@ mod test {
644
680
chunk_height : 4 ,
645
681
bits_per_sample : 16 ,
646
682
samples_per_pixel : 1 ,
683
+ planar_configuration : PlanarConfiguration :: Chunky ,
647
684
} ;
648
685
let input = Bytes :: from_owner ( diffed) ;
649
686
assert_eq ! (
@@ -672,6 +709,7 @@ mod test {
672
709
chunk_height : 4 ,
673
710
bits_per_sample : 16 ,
674
711
samples_per_pixel : 1 ,
712
+ planar_configuration : PlanarConfiguration :: Chunky ,
675
713
} ;
676
714
let input = Bytes :: from_owner ( diffed) ;
677
715
assert_eq ! (
@@ -699,6 +737,7 @@ mod test {
699
737
chunk_height : 2 ,
700
738
bits_per_sample : 32 ,
701
739
samples_per_pixel : 1 ,
740
+ planar_configuration : PlanarConfiguration :: Chunky ,
702
741
} ;
703
742
let input = Bytes :: from_owner ( diffed) ;
704
743
assert_eq ! (
@@ -732,6 +771,7 @@ mod test {
732
771
chunk_height : 2 ,
733
772
bits_per_sample : 64 ,
734
773
samples_per_pixel : 1 ,
774
+ planar_configuration : PlanarConfiguration :: Chunky ,
735
775
} ;
736
776
let input = Bytes :: from_owner ( diffed) ;
737
777
assert_eq ! (
0 commit comments