@@ -109,6 +109,8 @@ impl RevPredict for RevHorizontalPredictor {
109109/// Reverse predictor convenienve function for horizontal differencing
110110///
111111/// From image-tiff
112+ ///
113+ /// This should be used _after_ endianness fixing
112114pub fn rev_hpredict_nsamp ( buf : & mut [ u8 ] , bit_depth : u16 , samples : usize ) {
113115 match bit_depth {
114116 0 ..=8 => {
@@ -203,7 +205,7 @@ impl RevPredict for RevFloatingPointPredictor {
203205 16 => rev_predict_f16 ( in_buf, out_buf, predictor_info. samples_per_pixel as _ ) ,
204206 32 => rev_predict_f32 ( in_buf, out_buf, predictor_info. samples_per_pixel as _ ) ,
205207 64 => rev_predict_f64 ( in_buf, out_buf, predictor_info. samples_per_pixel as _ ) ,
206- _ => panic ! ( "thou shalt not predict with float16 " ) ,
208+ _ => panic ! ( "thou shalt not predict f24 " ) ,
207209 }
208210 }
209211 } else {
@@ -219,15 +221,18 @@ impl RevPredict for RevFloatingPointPredictor {
219221 {
220222 let mut out_row = BytesMut :: zeroed ( input_row_stride) ;
221223 match bit_depth {
222- 16 => rev_predict_f16 ( in_buf, out_buf, predictor_info. samples_per_pixel as _ ) ,
224+ 16 => {
225+ rev_predict_f16 ( in_buf, & mut out_row, predictor_info. samples_per_pixel as _ )
226+ }
223227 32 => {
224228 rev_predict_f32 ( in_buf, & mut out_row, predictor_info. samples_per_pixel as _ )
225229 }
226230 64 => {
227231 rev_predict_f64 ( in_buf, & mut out_row, predictor_info. samples_per_pixel as _ )
228232 }
229- _ => panic ! ( "thou shalt not predict f16 " ) ,
233+ _ => panic ! ( "thou shalt not predict f24 " ) ,
230234 }
235+ // remove the padding bytes
231236 out_buf. copy_from_slice ( & out_row[ ..output_row_stride] ) ;
232237 }
233238 }
@@ -250,7 +255,7 @@ pub fn rev_predict_f16(input: &mut [u8], output: &mut [u8], samples: usize) {
250255 for ( i, chunk) in output. chunks_mut ( 2 ) . enumerate ( ) {
251256 chunk. copy_from_slice ( & u16:: to_ne_bytes (
252257 // convert to native-endian
253- // preserve original byte-order
258+ // floating predictor is be-like
254259 u16:: from_be_bytes ( [ input[ i] , input[ input. len ( ) / 2 + i] ] ) ,
255260 ) ) ;
256261 }
@@ -267,20 +272,20 @@ pub fn rev_predict_f32(input: &mut [u8], output: &mut [u8], samples: usize) {
267272 for i in samples..input. len ( ) {
268273 input[ i] = input[ i] . wrapping_add ( input[ i - samples] ) ;
269274 }
270- println ! ( "output: {output:?}, {:?}" , output. len( ) ) ;
271275 // reverse byte shuffle and fix endianness
272276 for ( i, chunk) in output. chunks_mut ( 4 ) . enumerate ( ) {
273- println ! ( "i:{i:?}" ) ;
274- chunk. copy_from_slice ( & u32:: to_ne_bytes (
277+ chunk. copy_from_slice (
275278 // convert to native-endian
276- // preserve original byte-order
277- u32:: from_be_bytes ( [
278- input[ i] ,
279- input[ input. len ( ) / 4 + i] ,
280- input[ input. len ( ) / 4 * 2 + i] ,
281- input[ input. len ( ) / 4 * 3 + i] ,
282- ] ) ,
283- ) ) ;
279+ & u32:: to_ne_bytes (
280+ // floating predictor is be-like
281+ u32:: from_be_bytes ( [
282+ input[ i] ,
283+ input[ input. len ( ) / 4 + i] ,
284+ input[ input. len ( ) / 4 * 2 + i] ,
285+ input[ input. len ( ) / 4 * 3 + i] ,
286+ ] ) ,
287+ ) ,
288+ ) ;
284289 }
285290}
286291
@@ -295,16 +300,22 @@ pub fn rev_predict_f64(input: &mut [u8], output: &mut [u8], samples: usize) {
295300 }
296301
297302 for ( i, chunk) in output. chunks_mut ( 8 ) . enumerate ( ) {
298- chunk. copy_from_slice ( & u64:: to_ne_bytes ( u64:: from_be_bytes ( [
299- input[ i] ,
300- input[ input. len ( ) / 8 + i] ,
301- input[ input. len ( ) / 8 * 2 + i] ,
302- input[ input. len ( ) / 8 * 3 + i] ,
303- input[ input. len ( ) / 8 * 4 + i] ,
304- input[ input. len ( ) / 8 * 5 + i] ,
305- input[ input. len ( ) / 8 * 6 + i] ,
306- input[ input. len ( ) / 8 * 7 + i] ,
307- ] ) ) ) ;
303+ chunk. copy_from_slice (
304+ // convert to native-endian
305+ & u64:: to_ne_bytes (
306+ // floating predictor is be-like
307+ u64:: from_be_bytes ( [
308+ input[ i] ,
309+ input[ input. len ( ) / 8 + i] ,
310+ input[ input. len ( ) / 8 * 2 + i] ,
311+ input[ input. len ( ) / 8 * 3 + i] ,
312+ input[ input. len ( ) / 8 * 4 + i] ,
313+ input[ input. len ( ) / 8 * 5 + i] ,
314+ input[ input. len ( ) / 8 * 6 + i] ,
315+ input[ input. len ( ) / 8 * 7 + i] ,
316+ ] ) ,
317+ ) ,
318+ ) ;
308319 }
309320}
310321
@@ -453,7 +464,7 @@ mod test {
453464 assert_eq ! ( p. rev_predict_fix_endianness( buffer, & predictor_info, x, y) . unwrap( ) , res) ;
454465 println ! ( "testing i32" ) ;
455466 predictor_info. bits_per_sample = & [ 32 ] ;
456- let buffer = Bytes :: from ( input. iter ( ) . flat_map ( |v| ( * v as i32 ) . to_le_bytes ( ) ) . collect :: < Vec < _ > > ( ) ) ;
467+ let buffer = Bytes :: from ( input. iter ( ) . flat_map ( |v| v . to_le_bytes ( ) ) . collect :: < Vec < _ > > ( ) ) ;
457468 let res = Bytes :: from ( expected. iter ( ) . flat_map ( |v| ( * v as i32 ) . to_ne_bytes ( ) ) . collect :: < Vec < _ > > ( ) ) ;
458469 assert_eq ! ( p. rev_predict_fix_endianness( buffer, & predictor_info, x, y) . unwrap( ) , res) ;
459470 println ! ( "testing i64" ) ;
@@ -508,7 +519,7 @@ mod test {
508519 assert_eq ! ( -1i32 as u32 , u32 :: MAX ) ;
509520 println ! ( "testing i32" ) ;
510521 predictor_info. bits_per_sample = & [ 32 ] ;
511- let buffer = Bytes :: from ( input. iter ( ) . flat_map ( |v| ( * v as i32 ) . to_be_bytes ( ) ) . collect :: < Vec < _ > > ( ) ) ;
522+ let buffer = Bytes :: from ( input. iter ( ) . flat_map ( |v| v . to_be_bytes ( ) ) . collect :: < Vec < _ > > ( ) ) ;
512523 let res = Bytes :: from ( expected. iter ( ) . flat_map ( |v| ( * v as i32 ) . to_ne_bytes ( ) ) . collect :: < Vec < _ > > ( ) ) ;
513524 assert_eq ! ( p. rev_predict_fix_endianness( buffer, & predictor_info, x, y) . unwrap( ) , res) ;
514525 assert_eq ! ( -1i32 as u64 , u64 :: MAX ) ;
@@ -520,57 +531,129 @@ mod test {
520531 }
521532 }
522533
523- // #[rustfmt::skip]
534+ #[ rustfmt:: skip]
535+ #[ test]
536+ fn test_predict_f16 ( ) {
537+ // take a 4-value image
538+ let expect_le = [ 1 , 0 , 3 , 2 , 5 , 4 , 7 , 6u8 ] ;
539+ let _expected = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7u8 ] ;
540+ // 0 1
541+ // 0 1
542+ // 0 1
543+ // 0 1
544+ let _shuffled = [ 0 , 2 , 4 , 6 , 1 , 3 , 5 , 7u8 ] ;
545+ let diffed = [ 0 , 2 , 2 , 2 , 251 , 2 , 2 , 2 ] ;
546+ let info = PredictorInfo {
547+ endianness : Endianness :: LittleEndian ,
548+ image_width : 4 +4 ,
549+ image_height : 4 +1 ,
550+ chunk_width : 4 ,
551+ chunk_height : 4 ,
552+ bits_per_sample : & [ 16 ] ,
553+ samples_per_pixel : 1 ,
554+ sample_format : & [ SampleFormat :: IEEEFP ] ,
555+ planar_configuration : PlanarConfiguration :: Chunky ,
556+ } ;
557+ let input = Bytes :: from_owner ( diffed) ;
558+ assert_eq ! (
559+ & RevFloatingPointPredictor . rev_predict_fix_endianness( input, & info, 1 , 1 ) . unwrap( ) [ ..] ,
560+ & expect_le[ ..]
561+ )
562+ }
563+
564+ #[ rustfmt:: skip]
565+ #[ test]
566+ fn test_predict_f16_padding ( ) {
567+ // take a 4-pixel image with 2 padding pixels
568+ let expect_le = [ 1 , 0 , 3 , 2u8 ] ; // no padding
569+ let _expected = [ 0 , 1 , 2 , 3 , 0 , 0 , 0 , 0u8 ] ; //padding added
570+ // 0 1
571+ // 0 1
572+ // 0 1
573+ // 0 1
574+ let _shuffled = [ 0 , 2 , 0 , 0 , 1 , 3 , 0 , 0u8 ] ;
575+ let diffed = [ 0 , 2 , 254 , 0 , 1 , 2 , 253 , 0 ] ;
576+ let info = PredictorInfo {
577+ endianness : Endianness :: LittleEndian ,
578+ image_width : 4 +2 ,
579+ image_height : 4 +1 ,
580+ chunk_width : 4 ,
581+ chunk_height : 4 ,
582+ bits_per_sample : & [ 16 ] ,
583+ samples_per_pixel : 1 ,
584+ sample_format : & [ SampleFormat :: IEEEFP ] ,
585+ planar_configuration : PlanarConfiguration :: Chunky ,
586+ } ;
587+ let input = Bytes :: from_owner ( diffed) ;
588+ assert_eq ! (
589+ & RevFloatingPointPredictor . rev_predict_fix_endianness( input, & info, 1 , 1 ) . unwrap( ) [ ..] ,
590+ & expect_le[ ..]
591+ )
592+ }
593+
594+ #[ rustfmt:: skip]
524595 #[ test]
525596 fn test_fpredict_f32 ( ) {
597+ // let's take this 2-value image where we only look at bytes
598+ let expect_le = [ 3 , 2 , 1 , 0 , 7 , 6 , 5 , 4 ] ;
599+ let _expected = vec ! [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7u8 ] ;
600+ // 0 1 2 3 \_ de-shuffling indices
601+ // 0 1 2 3 / (the one the function uses)
602+ let _shuffled = vec ! [ 0 , 4 , 1 , 5 , 2 , 6 , 3 , 7u8 ] ;
603+ let diffed = vec ! [ 0 , 4 , 253 , 4 , 253 , 4 , 253 , 4u8 ] ;
604+ println ! ( "expected: {expect_le:?}" ) ;
605+ let mut info = PredictorInfo {
606+ endianness : Endianness :: LittleEndian ,
607+ image_width : 2 ,
608+ image_height : 2 + 1 ,
609+ chunk_width : 2 ,
610+ chunk_height : 2 ,
611+ bits_per_sample : & [ 32 ] ,
612+ samples_per_pixel : 1 ,
613+ sample_format : & [ SampleFormat :: IEEEFP ] ,
614+ planar_configuration : PlanarConfiguration :: Chunky ,
615+ } ;
616+ let input = Bytes :: from_owner ( diffed) ;
617+ assert_eq ! (
618+ & RevFloatingPointPredictor
619+ . rev_predict_fix_endianness( input. clone( ) , & info, 0 , 1 ) . unwrap( ) [ ..] ,
620+ & expect_le
621+ ) ;
622+ info. endianness = Endianness :: BigEndian ;
623+ assert_eq ! (
624+ & RevFloatingPointPredictor . rev_predict_fix_endianness( input, & info, 0 , 1 ) . unwrap( ) [ ..] ,
625+ & expect_le
626+ )
627+ }
628+
629+ #[ rustfmt:: skip]
630+ #[ test]
631+ fn test_fpredict_f64 ( ) {
632+ assert_eq ! ( f64 :: from_le_bytes( [ 7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 ] ) , f64 :: from_bits( 0x00_01_02_03_04_05_06_07 ) ) ;
526633 // let's take this 2-value image
527- let expected: Vec < u8 > = [ 42.0f32 , 43.0 ]
528- . iter ( )
529- . flat_map ( |f| f. to_le_bytes ( ) )
530- . collect ( ) ;
531- assert_eq ! ( expected, vec![ 0x0 , 0x0 , 0x28 , 0x42 , 0x0 , 0x0 , 0x2c , 0x42 ] ) ;
634+ let expect_be = [ 7 , 6 , 5 , 4 , 3 , 2 , 1 , 0 , 15 , 14 , 13 , 12 , 11 , 10 , 9 , 8 ] ;
635+ let _expected = [ 0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11 , 12 , 13 , 14 , 15u8 ] ;
636+ // 0 1 2 3 4 5 6 7
637+ // 0 1 2 3 4 5 6 7
638+ let _shuffled = [ 0 , 8 , 1 , 9 , 2 , 10 , 3 , 11 , 4 , 12 , 5 , 13 , 6 , 14 , 7 , 15u8 ] ;
639+ let diffed = [ 0 , 8 , 249 , 8 , 249 , 8 , 249 , 8 , 249 , 8 , 249 , 8 , 249 , 8 , 249 , 8u8 ] ;
532640 let info = PredictorInfo {
533641 endianness : Endianness :: LittleEndian ,
534642 image_width : 2 ,
535643 image_height : 2 + 1 ,
536644 chunk_width : 2 ,
537645 chunk_height : 2 ,
538- bits_per_sample : & [ 32 ] ,
646+ bits_per_sample : & [ 64 ] ,
539647 samples_per_pixel : 1 ,
540648 sample_format : & [ SampleFormat :: IEEEFP ] ,
541649 planar_configuration : PlanarConfiguration :: Chunky ,
542650 } ;
543- let input = Bytes :: from_static ( & [ 0x42u8 , 0 , 230 , 4 , 212 , 0 , 0 , 0 ] ) ;
651+ let input = Bytes :: from_owner ( diffed ) ;
544652 assert_eq ! (
545- RevFloatingPointPredictor
653+ & RevFloatingPointPredictor
546654 . rev_predict_fix_endianness( input, & info, 0 , 1 )
547- . unwrap( ) ,
548- expected
655+ . unwrap( ) [ .. ] ,
656+ & expect_be [ .. ]
549657 ) ;
550658 }
551-
552- // #[test]
553- // fn test_fpredict_f64() {
554- // // let's take this 2-value image
555- // let expected: Vec<u8> = [42.0f64, 43.0].iter().flat_map(|f| f.to_le_bytes()).collect();
556- // assert_eq!(expected, vec![0,0,0,0,0,0,69,64,0,0,0,0,0,128,69,64]);
557- // let info = PredictorInfo {
558- // endianness: Endianness::LittleEndian,
559- // image_width: 2,
560- // image_height: 2 + 1,
561- // chunk_width: 2,
562- // chunk_height: 2,
563- // bits_per_sample: &[64],
564- // samples_per_pixel: 1,
565- // sample_format: &[SampleFormat::IEEEFP],
566- // planar_configuration: PlanarConfiguration::Chunky,
567- // };
568- // let input = Bytes::from_static(&[0x42u8, 0, 230, 4, 212, 0, 0, 0]);
569- // assert_eq!(
570- // RevFloatingPointPredictor
571- // .rev_predict_fix_endianness(input, &info, 0, 1)
572- // .unwrap(),
573- // expected
574- // );
575- // }
576659}
0 commit comments