Skip to content

Commit 78888b1

Browse files
JPEG: Optimise output functions in some cases
1 parent c294041 commit 78888b1

File tree

1 file changed

+124
-25
lines changed

1 file changed

+124
-25
lines changed

MCGalaxy/util/Imaging/JpegDecoder.cs

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

Comments
 (0)