@@ -4,6 +4,7 @@ use std::fmt::Debug;
44use bytes:: { Bytes , BytesMut } ;
55
66use crate :: error:: AsyncTiffError ;
7+ use crate :: tiff:: tags:: PlanarConfiguration ;
78use crate :: ImageFileDirectory ;
89use 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
3942impl 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