@@ -484,9 +484,6 @@ impl<R: Read> Decoder<R> {
484
484
}
485
485
}
486
486
487
- let blocks_per_mcu: Vec < u16 > = components. iter ( )
488
- . map ( |c| c. horizontal_sampling_factor as u16 * c. vertical_sampling_factor as u16 )
489
- . collect ( ) ;
490
487
let is_progressive = frame. coding_process == CodingProcess :: DctProgressive ;
491
488
let is_interleaved = components. len ( ) > 1 ;
492
489
let mut dummy_block = [ 0i16 ; 64 ] ;
@@ -504,70 +501,37 @@ impl<R: Read> Decoder<R> {
504
501
}
505
502
}
506
503
507
- for mcu_y in 0 .. frame. mcu_size . height {
508
- for mcu_x in 0 .. frame. mcu_size . width {
509
- for ( i, component) in components. iter ( ) . enumerate ( ) {
510
- for j in 0 .. blocks_per_mcu[ i] {
511
- let ( block_x, block_y) = if is_interleaved {
512
- // Section A.2.3
513
- ( mcu_x * component. horizontal_sampling_factor as u16 + j % component. horizontal_sampling_factor as u16 ,
514
- mcu_y * component. vertical_sampling_factor as u16 + j / component. horizontal_sampling_factor as u16 )
515
- }
516
- else {
517
- // Section A.2.2
518
-
519
- let blocks_per_row = component. block_size . width as usize ;
520
- let block_num = ( mcu_y as usize * frame. mcu_size . width as usize +
521
- mcu_x as usize ) * blocks_per_mcu[ i] as usize + j as usize ;
522
-
523
- let x = ( block_num % blocks_per_row) as u16 ;
524
- let y = ( block_num / blocks_per_row) as u16 ;
525
-
526
- if x * component. dct_scale as u16 >= component. size . width || y * component. dct_scale as u16 >= component. size . height {
527
- continue ;
528
- }
504
+ // 4.8.2
505
+ // When reading from the stream, if the data is non-interleaved then an MCU consists of
506
+ // exactly one block (effectively a 1x1 sample).
507
+ let ( mcu_horizontal_samples, mcu_vertical_samples) = if is_interleaved {
508
+ let horizontal = components. iter ( ) . map ( |component| component. horizontal_sampling_factor as u16 ) . collect :: < Vec < _ > > ( ) ;
509
+ let vertical = components. iter ( ) . map ( |component| component. vertical_sampling_factor as u16 ) . collect :: < Vec < _ > > ( ) ;
510
+ ( horizontal, vertical)
511
+ } else {
512
+ ( vec ! [ 1 ] , vec ! [ 1 ] )
513
+ } ;
529
514
530
- ( x, y)
531
- } ;
515
+ // This also affects how many MCU values we read from stream. If it's a non-interleaved stream,
516
+ // the MCUs will be exactly the block count.
517
+ let ( max_mcu_x, max_mcu_y) = if is_interleaved {
518
+ ( frame. mcu_size . width , frame. mcu_size . height )
519
+ } else {
520
+ ( components[ 0 ] . block_size . width , components[ 0 ] . block_size . height )
521
+ } ;
532
522
533
- let block_offset = ( block_y as usize * component. block_size . width as usize + block_x as usize ) * 64 ;
534
- let mcu_row_offset = mcu_y as usize * component. block_size . width as usize * component. vertical_sampling_factor as usize * 64 ;
535
- let coefficients = if is_progressive {
536
- & mut self . coefficients [ scan. component_indices [ i] ] [ block_offset .. block_offset + 64 ]
537
- } else if finished[ i] {
538
- & mut mcu_row_coefficients[ i] [ block_offset - mcu_row_offset .. block_offset - mcu_row_offset + 64 ]
539
- } else {
540
- & mut dummy_block[ ..]
541
- } ;
523
+ for mcu_y in 0 ..max_mcu_y {
524
+ if mcu_y * 8 >= frame. image_size . height {
525
+ break ;
526
+ }
542
527
543
- if scan. successive_approximation_high == 0 {
544
- decode_block ( & mut self . reader ,
545
- coefficients,
546
- & mut huffman,
547
- self . dc_huffman_tables [ scan. dc_table_indices [ i] ] . as_ref ( ) ,
548
- self . ac_huffman_tables [ scan. ac_table_indices [ i] ] . as_ref ( ) ,
549
- scan. spectral_selection . clone ( ) ,
550
- scan. successive_approximation_low ,
551
- & mut eob_run,
552
- & mut dc_predictors[ i] ) ?;
553
- }
554
- else {
555
- decode_block_successive_approximation ( & mut self . reader ,
556
- coefficients,
557
- & mut huffman,
558
- self . ac_huffman_tables [ scan. ac_table_indices [ i] ] . as_ref ( ) ,
559
- scan. spectral_selection . clone ( ) ,
560
- scan. successive_approximation_low ,
561
- & mut eob_run) ?;
562
- }
563
- }
528
+ for mcu_x in 0 ..max_mcu_x {
529
+ if mcu_x * 8 >= frame. image_size . width {
530
+ break ;
564
531
}
565
532
566
533
if self . restart_interval > 0 {
567
- let is_last_mcu = mcu_x == frame. mcu_size . width - 1 && mcu_y == frame. mcu_size . height - 1 ;
568
- mcus_left_until_restart -= 1 ;
569
-
570
- if mcus_left_until_restart == 0 && !is_last_mcu {
534
+ if mcus_left_until_restart == 0 {
571
535
match huffman. take_marker ( & mut self . reader ) ? {
572
536
Some ( Marker :: RST ( n) ) => {
573
537
if n != expected_rst_num {
@@ -587,16 +551,86 @@ impl<R: Read> Decoder<R> {
587
551
None => return Err ( Error :: Format ( format ! ( "no marker found where RST{} was expected" , expected_rst_num) ) ) ,
588
552
}
589
553
}
554
+
555
+ mcus_left_until_restart -= 1 ;
556
+ }
557
+
558
+ for ( i, component) in components. iter ( ) . enumerate ( ) {
559
+ for v_pos in 0 ..mcu_vertical_samples[ i] {
560
+ for h_pos in 0 ..mcu_horizontal_samples[ i] {
561
+ let coefficients = if is_progressive {
562
+ let block_y = ( mcu_y * mcu_vertical_samples[ i] + v_pos) as usize ;
563
+ let block_x = ( mcu_x * mcu_horizontal_samples[ i] + h_pos) as usize ;
564
+ let block_offset = ( block_y * component. block_size . width as usize + block_x) * 64 ;
565
+ & mut self . coefficients [ scan. component_indices [ i] ] [ block_offset..block_offset + 64 ]
566
+ } else if finished[ i] {
567
+ // Because the worker thread operates in batches as if we were always interleaved, we
568
+ // need to distinguish between a single-shot buffer and one that's currently in process
569
+ // (for a non-interleaved) stream
570
+ let mcu_batch_current_row = if is_interleaved {
571
+ 0
572
+ } else {
573
+ mcu_y % component. vertical_sampling_factor as u16
574
+ } ;
575
+
576
+ let block_y = ( mcu_batch_current_row * mcu_vertical_samples[ i] + v_pos) as usize ;
577
+ let block_x = ( mcu_x * mcu_horizontal_samples[ i] + h_pos) as usize ;
578
+ let block_offset = ( block_y * component. block_size . width as usize + block_x) * 64 ;
579
+ & mut mcu_row_coefficients[ i] [ block_offset..block_offset + 64 ]
580
+ } else {
581
+ & mut dummy_block[ ..]
582
+ } ;
583
+
584
+ if scan. successive_approximation_high == 0 {
585
+ decode_block ( & mut self . reader ,
586
+ coefficients,
587
+ & mut huffman,
588
+ self . dc_huffman_tables [ scan. dc_table_indices [ i] ] . as_ref ( ) ,
589
+ self . ac_huffman_tables [ scan. ac_table_indices [ i] ] . as_ref ( ) ,
590
+ scan. spectral_selection . clone ( ) ,
591
+ scan. successive_approximation_low ,
592
+ & mut eob_run,
593
+ & mut dc_predictors[ i] ) ?;
594
+ }
595
+ else {
596
+ decode_block_successive_approximation ( & mut self . reader ,
597
+ coefficients,
598
+ & mut huffman,
599
+ self . ac_huffman_tables [ scan. ac_table_indices [ i] ] . as_ref ( ) ,
600
+ scan. spectral_selection . clone ( ) ,
601
+ scan. successive_approximation_low ,
602
+ & mut eob_run) ?;
603
+ }
604
+ }
605
+ }
590
606
}
591
607
}
592
608
593
609
// Send the coefficients from this MCU row to the worker thread for dequantization and idct.
594
610
for ( i, component) in components. iter ( ) . enumerate ( ) {
595
611
if finished[ i] {
612
+ // In the event of non-interleaved streams, if we're still building the buffer out,
613
+ // keep going; don't send it yet. We also need to ensure we don't skip over the last
614
+ // row(s) of the image.
615
+ if !is_interleaved && ( mcu_y + 1 ) * 8 < frame. image_size . height {
616
+ if ( mcu_y + 1 ) % component. vertical_sampling_factor as u16 > 0 {
617
+ continue ;
618
+ }
619
+ }
620
+
596
621
let coefficients_per_mcu_row = component. block_size . width as usize * component. vertical_sampling_factor as usize * 64 ;
597
622
598
623
let row_coefficients = if is_progressive {
599
- let offset = mcu_y as usize * coefficients_per_mcu_row;
624
+ // Because non-interleaved streams will have multiple MCU rows concatenated together,
625
+ // the row for calculating the offset is different.
626
+ let worker_mcu_y = if is_interleaved {
627
+ mcu_y
628
+ } else {
629
+ // Explicitly doing floor-division here
630
+ mcu_y / component. vertical_sampling_factor as u16
631
+ } ;
632
+
633
+ let offset = worker_mcu_y as usize * coefficients_per_mcu_row;
600
634
self . coefficients [ scan. component_indices [ i] ] [ offset .. offset + coefficients_per_mcu_row] . to_vec ( )
601
635
} else {
602
636
mem:: replace ( & mut mcu_row_coefficients[ i] , vec ! [ 0i16 ; coefficients_per_mcu_row] )
0 commit comments