@@ -268,13 +268,26 @@ void SetHuffTables(byte compID, byte tables) {
268268 } ;
269269
270270 const int BLOCK_SAMPLES = 8 ;
271+ const int BLOCK_SIZE = 8 * 8 ;
272+
273+ struct YCbCr { public float Y , Cb , Cr ; } ;
274+
271275 void DecodeMCUs ( byte [ ] src , SimpleBitmap bmp ) {
272- int mcus_x = Utils . CeilDiv ( bmp . Width , lowestHor * BLOCK_SAMPLES ) ;
273- int mcus_y = Utils . CeilDiv ( bmp . Height , lowestVer * BLOCK_SAMPLES ) ;
276+ int mcu_w = lowestHor * BLOCK_SAMPLES ;
277+ int mcu_h = lowestVer * BLOCK_SAMPLES ;
278+ int mcus_x = Utils . CeilDiv ( bmp . Width , mcu_w ) ;
279+ int mcus_y = Utils . CeilDiv ( bmp . Height , mcu_h ) ;
274280
275281 JpegComponent [ ] comps = this . comps ;
276- int [ ] block = new int [ 64 ] ;
277- float [ ] output = new float [ 64 ] ;
282+ int [ ] block = new int [ BLOCK_SIZE ] ;
283+ float [ ] output = new float [ BLOCK_SIZE ] ;
284+
285+ YCbCr [ ] colors = new YCbCr [ mcu_w * mcu_h ] ;
286+ for ( int i = 0 ; i < colors . Length ; i ++ )
287+ {
288+ colors [ i ] . Cr = 128 ;
289+ colors [ i ] . Cb = 128 ;
290+ }
278291
279292 for ( int mcuY = 0 ; mcuY < mcus_y ; mcuY ++ )
280293 for ( int mcuX = 0 ; mcuX < mcus_x ; mcuX ++ )
@@ -283,29 +296,66 @@ void DecodeMCUs(byte[] src, SimpleBitmap bmp) {
283296 {
284297 JpegComponent comp = comps [ i ] ;
285298
286- for ( int blockY = 0 ; blockY < comp . BlocksPerMcuY ; blockY ++ )
287- for ( int blockX = 0 ; blockX < comp . BlocksPerMcuX ; blockX ++ )
299+ for ( int by = 0 ; by < comp . BlocksPerMcuY ; by ++ )
300+ for ( int bx = 0 ; bx < comp . BlocksPerMcuX ; bx ++ )
288301 {
289302 DecodeBlock ( comp , src , block , output ) ;
290303 IDCT ( block , output ) ;
304+
305+ int samplesX = lowestHor / comp . SamplingHor ;
306+ int samplesY = lowestVer / comp . SamplingVer ;
307+
308+ for ( int y = 0 ; y < BLOCK_SAMPLES ; y ++ )
309+ for ( int x = 0 ; x < BLOCK_SAMPLES ; x ++ )
310+ {
311+ for ( int py = 0 ; py < samplesY ; py ++ )
312+ for ( int px = 0 ; px < samplesX ; px ++ )
313+ {
314+ int YY = ( by * BLOCK_SAMPLES + y ) * samplesY + py ;
315+ int XX = ( bx * BLOCK_SAMPLES + x ) * samplesX + px ;
316+ int idx = YY * mcu_w + XX ;
317+
318+ if ( i == 0 )
319+ colors [ idx ] . Y = output [ y * BLOCK_SAMPLES + x ] ;
320+ else if ( i == 1 )
321+ colors [ idx ] . Cb = output [ y * BLOCK_SAMPLES + x ] ;
322+ else if ( i == 2 )
323+ colors [ idx ] . Cr = output [ y * BLOCK_SAMPLES + x ] ;
324+ }
325+ }
291326 }
327+ }
328+
329+ int baseX = mcuX * mcu_w ;
330+ int baseY = mcuY * mcu_h ;
331+ int j = 0 ;
332+
333+ for ( int YY = 0 ; YY < mcu_w ; YY ++ )
334+ for ( int XX = 0 ; XX < mcu_h ; XX ++ , j ++ )
335+ {
336+ int globalX = baseX + XX ;
337+ int globalY = baseY + YY ;
292338
293- for ( int YY = 0 ; YY < BLOCK_SAMPLES ; YY ++ )
294- for ( int XX = 0 ; XX < BLOCK_SAMPLES ; XX ++ )
295- {
296- int globalX = mcuX * BLOCK_SAMPLES + XX ;
297- int globalY = mcuY * BLOCK_SAMPLES + YY ;
339+ if ( globalX < bmp . Width && globalY < bmp . Height ) {
340+ float y = colors [ j ] . Y ;
341+ float cr = colors [ j ] . Cr ;
342+ float cb = colors [ j ] . Cb ;
298343
299- if ( globalX < bmp . Width && globalY < bmp . Height ) {
300- byte rgb = ( byte ) output [ YY * BLOCK_SAMPLES + XX ] ;
301- Pixel p = new Pixel ( rgb , rgb , rgb , 255 ) ;
302- bmp . pixels [ globalY * bmp . Width + globalX ] = p ;
303- }
344+ float r = 1.40200f * ( cr - 128 ) + y ;
345+ float g = - 0.34414f * ( cb - 128 ) - 0.71414f * ( cr - 128 ) + y ;
346+ float b = 1.77200f * ( cb - 128 ) + y ;
347+
348+ Pixel p = new Pixel ( ByteClamp ( r ) , ByteClamp ( g ) , ByteClamp ( b ) , 255 ) ;
349+ bmp . pixels [ globalY * bmp . Width + globalX ] = p ;
304350 }
305- // Fail("DE");
306351 }
307352 }
308- // Fail("MCUs");
353+ }
354+
355+ static byte ByteClamp ( float v ) {
356+ if ( v < 0 ) return 0 ;
357+ if ( v > 255 ) return 255 ;
358+ return ( byte ) v ;
309359 }
310360
311361 void DecodeBlock ( JpegComponent comp , byte [ ] src , int [ ] block , float [ ] output ) {
0 commit comments