Skip to content

Commit c8f121c

Browse files
JPEG: MCUs now decoded properly
1 parent cfd6ca6 commit c8f121c

File tree

1 file changed

+68
-18
lines changed

1 file changed

+68
-18
lines changed

MCGalaxy/util/Imaging/JpegDecoder.cs

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)