@@ -257,6 +257,7 @@ void ReadFrameStart(byte[] src, SimpleBitmap bmp) {
257257
258258 comp . SamplesPerBlockX = ( byte ) ( lowestHor / comp . BlocksPerMcuX ) ;
259259 comp . SamplesPerBlockY = ( byte ) ( lowestVer / comp . BlocksPerMcuY ) ;
260+ comp . OutputBlock = GetBlockOutputFunction ( comp ) ;
260261 }
261262 }
262263
@@ -306,8 +307,6 @@ void SetHuffTables(byte compID, byte tables) {
306307 const int BLOCK_SAMPLES = 8 ;
307308 const int BLOCK_SIZE = 8 * 8 ;
308309
309- struct YCbCr { public float Y , Cb , Cr ; } ;
310-
311310 void DecodeMCUs ( byte [ ] src , SimpleBitmap bmp ) {
312311 int mcu_w = lowestHor * BLOCK_SAMPLES ;
313312 int mcu_h = lowestVer * BLOCK_SAMPLES ;
@@ -346,26 +345,8 @@ void DecodeMCUs(byte[] src, SimpleBitmap bmp) {
346345 DecodeBlock ( comp , src , block ) ;
347346 IDCT ( block , output ) ;
348347
349- int samplesX = comp . SamplesPerBlockX ;
350- int samplesY = comp . SamplesPerBlockY ;
351-
352- for ( int y = 0 ; y < BLOCK_SAMPLES ; y ++ )
353- for ( int x = 0 ; x < BLOCK_SAMPLES ; x ++ )
354- {
355- float sample = output [ y * BLOCK_SAMPLES + x ] ;
356-
357- for ( int py = 0 ; py < samplesY ; py ++ )
358- for ( int px = 0 ; px < samplesX ; px ++ )
359- {
360- int YY = ( by * BLOCK_SAMPLES + y ) * samplesY + py ;
361- int XX = ( bx * BLOCK_SAMPLES + x ) * samplesX + px ;
362- int idx = YY * mcu_w + XX ;
363-
364- if ( i == 0 ) colors [ idx ] . Y = sample ;
365- else if ( i == 1 ) colors [ idx ] . Cb = sample ;
366- else if ( i == 2 ) colors [ idx ] . Cr = sample ;
367- }
368- }
348+ comp . OutputBlock ( comp , colors , mcu_w , i , output ,
349+ bx * BLOCK_SAMPLES , by * BLOCK_SAMPLES ) ;
369350 }
370351 }
371352
@@ -628,23 +609,141 @@ int ReadBiasedValue(byte[] src, int bits) {
628609 }
629610 return value ;
630611 }
612+
613+
614+ static JpegBlockOutput GetBlockOutputFunction ( JpegComponent comp ) {
615+ if ( comp . SamplesPerBlockX == 1 && comp . SamplesPerBlockY == 1 ) {
616+ if ( comp . ID == 1 ) return Y_1x1Output ;
617+ if ( comp . ID == 2 ) return Cb_1x1Output ;
618+ if ( comp . ID == 3 ) return Cr_1x1Output ;
619+ }
620+
621+ if ( comp . SamplesPerBlockX == 2 && comp . SamplesPerBlockY == 2 ) {
622+ if ( comp . ID == 2 ) return Cb_2x2Output ;
623+ if ( comp . ID == 3 ) return Cr_2x2Output ;
624+ }
625+ return Generic_BlockOutput ;
626+ }
627+
628+ static void Generic_BlockOutput ( JpegComponent comp , YCbCr [ ] colors , int mcu_w ,
629+ int i , float * output , int baseX , int baseY ) {
630+ int samplesX = comp . SamplesPerBlockX ;
631+ int samplesY = comp . SamplesPerBlockY ;
632+
633+ for ( int y = 0 ; y < BLOCK_SAMPLES ; y ++ )
634+ for ( int x = 0 ; x < BLOCK_SAMPLES ; x ++ )
635+ {
636+ float sample = output [ y * BLOCK_SAMPLES + x ] ;
637+
638+ for ( int py = 0 ; py < samplesY ; py ++ )
639+ for ( int px = 0 ; px < samplesX ; px ++ )
640+ {
641+ int YY = ( baseY + y ) * samplesY + py ;
642+ int XX = ( baseX + x ) * samplesX + px ;
643+ int idx = YY * mcu_w + XX ;
644+
645+ if ( i == 0 ) colors [ idx ] . Y = sample ;
646+ else if ( i == 1 ) colors [ idx ] . Cb = sample ;
647+ else if ( i == 2 ) colors [ idx ] . Cr = sample ;
648+ }
649+ }
650+ }
651+
652+
653+ static void Y_1x1Output ( JpegComponent comp , YCbCr [ ] colors , int mcu_w ,
654+ int i , float * output , int baseX , int baseY ) {
655+ for ( int y = 0 , src = 0 ; y < BLOCK_SAMPLES ; y ++ )
656+ {
657+ int dst = ( baseY + y ) * mcu_w + ( baseX + 0 ) ;
658+
659+ for ( int x = 0 ; x < BLOCK_SAMPLES ; x ++ )
660+ {
661+ colors [ dst ++ ] . Y = output [ src ++ ] ;
662+ }
663+ }
664+ }
665+ static void Cb_1x1Output ( JpegComponent comp , YCbCr [ ] colors , int mcu_w ,
666+ int i , float * output , int baseX , int baseY ) {
667+ for ( int y = 0 , src = 0 ; y < BLOCK_SAMPLES ; y ++ )
668+ {
669+ int dst = ( baseY + y ) * mcu_w + ( baseX + 0 ) ;
670+
671+ for ( int x = 0 ; x < BLOCK_SAMPLES ; x ++ )
672+ {
673+ colors [ dst ++ ] . Cb = output [ src ++ ] ;
674+ }
675+ }
676+ }
677+
678+ static void Cr_1x1Output ( JpegComponent comp , YCbCr [ ] colors , int mcu_w ,
679+ int i , float * output , int baseX , int baseY ) {
680+ for ( int y = 0 , src = 0 ; y < BLOCK_SAMPLES ; y ++ )
681+ {
682+ int dst = ( baseY + y ) * mcu_w + ( baseX + 0 ) ;
683+
684+ for ( int x = 0 ; x < BLOCK_SAMPLES ; x ++ )
685+ {
686+ colors [ dst ++ ] . Cr = output [ src ++ ] ;
687+ }
688+ }
689+ }
690+
691+
692+ static void Cb_2x2Output ( JpegComponent comp , YCbCr [ ] colors , int mcu_w ,
693+ int i , float * output , int baseX , int baseY ) {
694+ for ( int y = 0 , src = 0 ; y < BLOCK_SAMPLES ; y ++ )
695+ {
696+ int dst = ( ( baseY + y ) * 2 ) * mcu_w + ( baseX + 0 ) * 2 ;
697+ for ( int x = 0 ; x < BLOCK_SAMPLES ; x ++ , dst += 2 )
698+ {
699+ float sample = output [ src ++ ] ;
700+ colors [ dst + 0 ] . Cb = sample ; // X + 0, Y + 0
701+ colors [ dst + 1 ] . Cb = sample ; // X + 1, Y + 0
702+ colors [ dst + mcu_w + 0 ] . Cb = sample ; // X + 0, Y + 1
703+ colors [ dst + mcu_w + 1 ] . Cb = sample ; // X + 1, Y + 1
704+ }
705+ }
706+ }
707+
708+ static void Cr_2x2Output ( JpegComponent comp , YCbCr [ ] colors , int mcu_w ,
709+ int i , float * output , int baseX , int baseY ) {
710+ for ( int y = 0 , src = 0 ; y < BLOCK_SAMPLES ; y ++ )
711+ {
712+ int dst = ( ( baseY + y ) * 2 ) * mcu_w + ( baseX + 0 ) * 2 ;
713+ for ( int x = 0 ; x < BLOCK_SAMPLES ; x ++ , dst += 2 )
714+ {
715+ float sample = output [ src ++ ] ;
716+ colors [ dst + 0 ] . Cr = sample ; // X + 0, Y + 0
717+ colors [ dst + 1 ] . Cr = sample ; // X + 1, Y + 0
718+ colors [ dst + mcu_w + 0 ] . Cr = sample ; // X + 0, Y + 1
719+ colors [ dst + mcu_w + 1 ] . Cr = sample ; // X + 1, Y + 1
720+ }
721+ }
722+ }
631723 }
632724
725+ struct YCbCr { public float Y , Cb , Cr ; } ;
726+
727+ unsafe delegate void JpegBlockOutput ( JpegComponent comp , YCbCr [ ] colors , int mcu_w ,
728+ int i , float * output , int baseX , int baseY ) ;
729+
633730 class JpegComponent
634731 {
635732 public byte ID ;
636- public byte QuantTable ;
733+ public byte QuantTable ;
637734 public byte ACHuffTable ;
638- public byte DCHuffTable ;
735+ public byte DCHuffTable ;
639736 public int PredDCValue ;
640737
641738 public byte BlocksPerMcuX ;
642- public byte BlocksPerMcuY ;
739+ public byte BlocksPerMcuY ;
643740 public byte SamplesPerBlockX ;
644741 public byte SamplesPerBlockY ;
645742
646743 public byte SamplingHor ;
647744 public byte SamplingVer ;
745+
746+ public JpegBlockOutput OutputBlock ;
648747 }
649748
650749 class HuffmanTable
0 commit comments