@@ -109,6 +109,8 @@ impl RevPredict for RevHorizontalPredictor {
109
109
/// Reverse predictor convenienve function for horizontal differencing
110
110
///
111
111
/// From image-tiff
112
+ ///
113
+ /// This should be used _after_ endianness fixing
112
114
pub fn rev_hpredict_nsamp ( buf : & mut [ u8 ] , bit_depth : u16 , samples : usize ) {
113
115
match bit_depth {
114
116
0 ..=8 => {
@@ -203,7 +205,7 @@ impl RevPredict for RevFloatingPointPredictor {
203
205
16 => rev_predict_f16 ( in_buf, out_buf, predictor_info. samples_per_pixel as _ ) ,
204
206
32 => rev_predict_f32 ( in_buf, out_buf, predictor_info. samples_per_pixel as _ ) ,
205
207
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 " ) ,
207
209
}
208
210
}
209
211
} else {
@@ -219,15 +221,18 @@ impl RevPredict for RevFloatingPointPredictor {
219
221
{
220
222
let mut out_row = BytesMut :: zeroed ( input_row_stride) ;
221
223
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
+ }
223
227
32 => {
224
228
rev_predict_f32 ( in_buf, & mut out_row, predictor_info. samples_per_pixel as _ )
225
229
}
226
230
64 => {
227
231
rev_predict_f64 ( in_buf, & mut out_row, predictor_info. samples_per_pixel as _ )
228
232
}
229
- _ => panic ! ( "thou shalt not predict f16 " ) ,
233
+ _ => panic ! ( "thou shalt not predict f24 " ) ,
230
234
}
235
+ // remove the padding bytes
231
236
out_buf. copy_from_slice ( & out_row[ ..output_row_stride] ) ;
232
237
}
233
238
}
@@ -250,7 +255,7 @@ pub fn rev_predict_f16(input: &mut [u8], output: &mut [u8], samples: usize) {
250
255
for ( i, chunk) in output. chunks_mut ( 2 ) . enumerate ( ) {
251
256
chunk. copy_from_slice ( & u16:: to_ne_bytes (
252
257
// convert to native-endian
253
- // preserve original byte-order
258
+ // floating predictor is be-like
254
259
u16:: from_be_bytes ( [ input[ i] , input[ input. len ( ) / 2 + i] ] ) ,
255
260
) ) ;
256
261
}
@@ -267,20 +272,20 @@ pub fn rev_predict_f32(input: &mut [u8], output: &mut [u8], samples: usize) {
267
272
for i in samples..input. len ( ) {
268
273
input[ i] = input[ i] . wrapping_add ( input[ i - samples] ) ;
269
274
}
270
- println ! ( "output: {output:?}, {:?}" , output. len( ) ) ;
271
275
// reverse byte shuffle and fix endianness
272
276
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 (
275
278
// 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
+ ) ;
284
289
}
285
290
}
286
291
@@ -295,16 +300,22 @@ pub fn rev_predict_f64(input: &mut [u8], output: &mut [u8], samples: usize) {
295
300
}
296
301
297
302
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
+ ) ;
308
319
}
309
320
}
310
321
@@ -453,7 +464,7 @@ mod test {
453
464
assert_eq ! ( p. rev_predict_fix_endianness( buffer, & predictor_info, x, y) . unwrap( ) , res) ;
454
465
println ! ( "testing i32" ) ;
455
466
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 < _ > > ( ) ) ;
457
468
let res = Bytes :: from ( expected. iter ( ) . flat_map ( |v| ( * v as i32 ) . to_ne_bytes ( ) ) . collect :: < Vec < _ > > ( ) ) ;
458
469
assert_eq ! ( p. rev_predict_fix_endianness( buffer, & predictor_info, x, y) . unwrap( ) , res) ;
459
470
println ! ( "testing i64" ) ;
@@ -508,7 +519,7 @@ mod test {
508
519
assert_eq ! ( -1i32 as u32 , u32 :: MAX ) ;
509
520
println ! ( "testing i32" ) ;
510
521
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 < _ > > ( ) ) ;
512
523
let res = Bytes :: from ( expected. iter ( ) . flat_map ( |v| ( * v as i32 ) . to_ne_bytes ( ) ) . collect :: < Vec < _ > > ( ) ) ;
513
524
assert_eq ! ( p. rev_predict_fix_endianness( buffer, & predictor_info, x, y) . unwrap( ) , res) ;
514
525
assert_eq ! ( -1i32 as u64 , u64 :: MAX ) ;
@@ -520,57 +531,129 @@ mod test {
520
531
}
521
532
}
522
533
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]
524
595
#[ test]
525
596
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 ) ) ;
526
633
// 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 ] ;
532
640
let info = PredictorInfo {
533
641
endianness : Endianness :: LittleEndian ,
534
642
image_width : 2 ,
535
643
image_height : 2 + 1 ,
536
644
chunk_width : 2 ,
537
645
chunk_height : 2 ,
538
- bits_per_sample : & [ 32 ] ,
646
+ bits_per_sample : & [ 64 ] ,
539
647
samples_per_pixel : 1 ,
540
648
sample_format : & [ SampleFormat :: IEEEFP ] ,
541
649
planar_configuration : PlanarConfiguration :: Chunky ,
542
650
} ;
543
- let input = Bytes :: from_static ( & [ 0x42u8 , 0 , 230 , 4 , 212 , 0 , 0 , 0 ] ) ;
651
+ let input = Bytes :: from_owner ( diffed ) ;
544
652
assert_eq ! (
545
- RevFloatingPointPredictor
653
+ & RevFloatingPointPredictor
546
654
. rev_predict_fix_endianness( input, & info, 0 , 1 )
547
- . unwrap( ) ,
548
- expected
655
+ . unwrap( ) [ .. ] ,
656
+ & expect_be [ .. ]
549
657
) ;
550
658
}
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
- // }
576
659
}
0 commit comments