@@ -251,8 +251,12 @@ void ReadFrameStart(byte[] src, SimpleBitmap bmp) {
251251 // In most JPEG images there is chroma sub-sampling
252252 for ( int i = 0 ; i < numComps ; i ++ )
253253 {
254- comps [ i ] . BlocksPerMcuX = comps [ i ] . SamplingHor ;
255- comps [ i ] . BlocksPerMcuY = comps [ i ] . SamplingVer ;
254+ JpegComponent comp = comps [ i ] ;
255+ comp . BlocksPerMcuX = comp . SamplingHor ;
256+ comp . BlocksPerMcuY = comp . SamplingVer ;
257+
258+ comp . SamplesPerBlockX = ( byte ) ( lowestHor / comp . BlocksPerMcuX ) ;
259+ comp . SamplesPerBlockY = ( byte ) ( lowestVer / comp . BlocksPerMcuY ) ;
256260 }
257261 }
258262
@@ -311,8 +315,11 @@ void DecodeMCUs(byte[] src, SimpleBitmap bmp) {
311315 int mcus_y = Utils . CeilDiv ( bmp . Height , mcu_h ) ;
312316
313317 JpegComponent [ ] comps = this . comps ;
314- int [ ] block = new int [ BLOCK_SIZE ] ;
318+ int * block = stackalloc int [ BLOCK_SIZE + 32 ] ;
315319 float * output = stackalloc float [ BLOCK_SIZE ] ;
320+ // NOTE: block has extra data at end, in case of invalid huffman code
321+ // resulting in 'num zeroes' going past limit of 64
322+ // Although there can be at most 15 extra zeroes, add 32 padding to be safe
316323
317324 YCbCr [ ] colors = new YCbCr [ mcu_w * mcu_h ] ;
318325
@@ -339,8 +346,8 @@ void DecodeMCUs(byte[] src, SimpleBitmap bmp) {
339346 DecodeBlock ( comp , src , block ) ;
340347 IDCT ( block , output ) ;
341348
342- int samplesX = lowestHor / comp . SamplingHor ;
343- int samplesY = lowestVer / comp . SamplingVer ;
349+ int samplesX = comp . SamplesPerBlockX ;
350+ int samplesY = comp . SamplesPerBlockY ;
344351
345352 for ( int y = 0 ; y < BLOCK_SAMPLES ; y ++ )
346353 for ( int x = 0 ; x < BLOCK_SAMPLES ; x ++ )
@@ -400,7 +407,7 @@ static byte ByteClamp(float v) {
400407 return ( byte ) v ;
401408 }
402409
403- void DecodeBlock ( JpegComponent comp , byte [ ] src , int [ ] block ) {
410+ void DecodeBlock ( JpegComponent comp , byte [ ] src , int * block ) {
404411 // DC value is relative to DC value from prior block
405412 var table = dc_huff_tables [ comp . DCHuffTable ] ;
406413 int dc_code = ReadHuffman ( table , src ) ;
@@ -410,7 +417,7 @@ void DecodeBlock(JpegComponent comp, byte[] src, int[] block) {
410417 comp . PredDCValue = dc_value ;
411418
412419 byte [ ] dequant = quant_tables [ comp . QuantTable ] ;
413- for ( int j = 0 ; j < block . Length ; j ++ ) block [ j ] = 0 ;
420+ for ( int j = 0 ; j < BLOCK_SIZE ; j ++ ) block [ j ] = 0 ;
414421 block [ 0 ] = dc_value * dequant [ 0 ] ;
415422
416423 // 63 AC values
@@ -455,7 +462,7 @@ void DecodeBlock(JpegComponent comp, byte[] src, int[] block) {
455462 const float C7 = 0.19509032201f / 4.0f ; // cos(7pi/16)
456463
457464 const int DCT_SIZE = 8 ;
458- static void IDCT ( int [ ] block , float * output ) {
465+ static void IDCT ( int * block , float * output ) {
459466 float * tmp = stackalloc float [ DCT_SIZE * DCT_SIZE ] ;
460467
461468 for ( int col = 0 ; col < DCT_SIZE ; col ++ )
@@ -626,16 +633,18 @@ int ReadBiasedValue(byte[] src, int bits) {
626633 class JpegComponent
627634 {
628635 public byte ID ;
629- public byte QuantTable ;
636+ public byte QuantTable ;
637+ public byte ACHuffTable ;
638+ public byte DCHuffTable ;
639+ public int PredDCValue ;
630640
631- public byte SamplingHor ;
632- public byte SamplingVer ;
633641 public byte BlocksPerMcuX ;
634- public byte BlocksPerMcuY ;
642+ public byte BlocksPerMcuY ;
643+ public byte SamplesPerBlockX ;
644+ public byte SamplesPerBlockY ;
635645
636- public byte ACHuffTable ;
637- public byte DCHuffTable ;
638- public int PredDCValue ;
646+ public byte SamplingHor ;
647+ public byte SamplingVer ;
639648 }
640649
641650 class HuffmanTable
0 commit comments