private void jpeg_idct_4x4(int component_index, short[] coef_block, int output_row, int output_col)
{
/* buffers data between passes */
int[] workspace = new int[JpegConstants.DCTSIZE * 4];
/* Pass 1: process columns from input, store into work array. */
int coefBlockIndex = 0;
int workspaceIndex = 0;
int[] quantTable = m_dctTables[component_index].int_array;
int quantTableIndex = 0;
for (int ctr = JpegConstants.DCTSIZE; ctr > 0; coefBlockIndex++, quantTableIndex++, workspaceIndex++, ctr--)
{
/* Don't bother to process column 4, because second pass won't use it */
if (ctr == JpegConstants.DCTSIZE - 4)
continue;
if (coef_block[coefBlockIndex + JpegConstants.DCTSIZE * 1] == 0 &&
coef_block[coefBlockIndex + JpegConstants.DCTSIZE * 2] == 0 &&
coef_block[coefBlockIndex + JpegConstants.DCTSIZE * 3] == 0 &&
coef_block[coefBlockIndex + JpegConstants.DCTSIZE * 5] == 0 &&
coef_block[coefBlockIndex + JpegConstants.DCTSIZE * 6] == 0 &&
coef_block[coefBlockIndex + JpegConstants.DCTSIZE * 7] == 0)
{
/* AC terms all zero; we need not examine term 4 for 4x4 output */
int dcval = REDUCED_DEQUANTIZE(coef_block[coefBlockIndex + JpegConstants.DCTSIZE * 0],
quantTable[quantTableIndex + JpegConstants.DCTSIZE * 0]) << REDUCED_PASS1_BITS;
workspace[workspaceIndex + JpegConstants.DCTSIZE * 0] = dcval;
workspace[workspaceIndex + JpegConstants.DCTSIZE * 1] = dcval;
workspace[workspaceIndex + JpegConstants.DCTSIZE * 2] = dcval;
workspace[workspaceIndex + JpegConstants.DCTSIZE * 3] = dcval;
continue;
}
/* Even part */
int tmp0 = REDUCED_DEQUANTIZE(coef_block[coefBlockIndex + JpegConstants.DCTSIZE * 0],
quantTable[quantTableIndex + JpegConstants.DCTSIZE * 0]);
tmp0 <<= (REDUCED_CONST_BITS + 1);
int z2 = REDUCED_DEQUANTIZE(coef_block[coefBlockIndex + JpegConstants.DCTSIZE * 2],
quantTable[quantTableIndex + JpegConstants.DCTSIZE * 2]);
int z3 = REDUCED_DEQUANTIZE(coef_block[coefBlockIndex + JpegConstants.DCTSIZE * 6],
quantTable[quantTableIndex + JpegConstants.DCTSIZE * 6]);
int tmp2 = z2 * REDUCED_FIX_1_847759065 + z3 * (-REDUCED_FIX_0_765366865);
int tmp10 = tmp0 + tmp2;
int tmp12 = tmp0 - tmp2;
/* Odd part */
int z1 = REDUCED_DEQUANTIZE(coef_block[coefBlockIndex + JpegConstants.DCTSIZE * 7],
quantTable[quantTableIndex + JpegConstants.DCTSIZE * 7]);
z2 = REDUCED_DEQUANTIZE(coef_block[coefBlockIndex + JpegConstants.DCTSIZE * 5],
quantTable[quantTableIndex + JpegConstants.DCTSIZE * 5]);
z3 = REDUCED_DEQUANTIZE(coef_block[coefBlockIndex + JpegConstants.DCTSIZE * 3],
quantTable[quantTableIndex + JpegConstants.DCTSIZE * 3]);
int z4 = REDUCED_DEQUANTIZE(coef_block[coefBlockIndex + JpegConstants.DCTSIZE * 1],
quantTable[quantTableIndex + JpegConstants.DCTSIZE * 1]);
tmp0 = z1 * (-REDUCED_FIX_0_211164243) /* sqrt(2) * (c3-c1) */ +
z2 * REDUCED_FIX_1_451774981 /* sqrt(2) * (c3+c7) */ +
z3 * (-REDUCED_FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ +
z4 * REDUCED_FIX_1_061594337; /* sqrt(2) * (c5+c7) */
tmp2 = z1 * (-REDUCED_FIX_0_509795579) /* sqrt(2) * (c7-c5) */ +
z2 * (-REDUCED_FIX_0_601344887) /* sqrt(2) * (c5-c1) */ +
z3 * REDUCED_FIX_0_899976223 /* sqrt(2) * (c3-c7) */ +
z4 * REDUCED_FIX_2_562915447; /* sqrt(2) * (c1+c3) */
/* Final output stage */
workspace[workspaceIndex + JpegConstants.DCTSIZE * 0] = JpegUtils.DESCALE(tmp10 + tmp2, REDUCED_CONST_BITS - REDUCED_PASS1_BITS + 1);
workspace[workspaceIndex + JpegConstants.DCTSIZE * 3] = JpegUtils.DESCALE(tmp10 - tmp2, REDUCED_CONST_BITS - REDUCED_PASS1_BITS + 1);
workspace[workspaceIndex + JpegConstants.DCTSIZE * 1] = JpegUtils.DESCALE(tmp12 + tmp0, REDUCED_CONST_BITS - REDUCED_PASS1_BITS + 1);
workspace[workspaceIndex + JpegConstants.DCTSIZE * 2] = JpegUtils.DESCALE(tmp12 - tmp0, REDUCED_CONST_BITS - REDUCED_PASS1_BITS + 1);
}
/* Pass 2: process 4 rows from work array, store into output array. */
byte[] limit = m_cinfo.m_sample_range_limit;
int limitOffset = m_cinfo.m_sampleRangeLimitOffset - RANGE_SUBSET;
workspaceIndex = 0;
for (int ctr = 0; ctr < 4; ctr++)
{
int currentOutRow = output_row + ctr;
/* It's not clear whether a zero row test is worthwhile here ... */
if (workspace[workspaceIndex + 1] == 0 &&
workspace[workspaceIndex + 2] == 0 &&
workspace[workspaceIndex + 3] == 0 &&
workspace[workspaceIndex + 5] == 0 &&
workspace[workspaceIndex + 6] == 0 &&
workspace[workspaceIndex + 7] == 0)
{
/* AC terms all zero */
byte dcval = limit[limitOffset + JpegUtils.DESCALE(workspace[workspaceIndex + 0], REDUCED_PASS1_BITS + 3) & RANGE_MASK];
m_componentBuffer[currentOutRow][output_col + 0] = dcval;
m_componentBuffer[currentOutRow][output_col + 1] = dcval;
m_componentBuffer[currentOutRow][output_col + 2] = dcval;
m_componentBuffer[currentOutRow][output_col + 3] = dcval;
workspaceIndex += JpegConstants.DCTSIZE; /* advance pointer to next row */
continue;
}
/* Even part */
int tmp0 = (workspace[workspaceIndex + 0]) << (REDUCED_CONST_BITS + 1);
int tmp2 = workspace[workspaceIndex + 2] * REDUCED_FIX_1_847759065 + workspace[workspaceIndex + 6] * (-REDUCED_FIX_0_765366865);
int tmp10 = tmp0 + tmp2;
int tmp12 = tmp0 - tmp2;
/* Odd part */
int z1 = workspace[workspaceIndex + 7];
int z2 = workspace[workspaceIndex + 5];
int z3 = workspace[workspaceIndex + 3];
int z4 = workspace[workspaceIndex + 1];
tmp0 = z1 * (-REDUCED_FIX_0_211164243) /* sqrt(2) * (c3-c1) */ +
z2 * REDUCED_FIX_1_451774981 /* sqrt(2) * (c3+c7) */ +
z3 * (-REDUCED_FIX_2_172734803) /* sqrt(2) * (-c1-c5) */ +
z4 * REDUCED_FIX_1_061594337; /* sqrt(2) * (c5+c7) */
tmp2 = z1 * (-REDUCED_FIX_0_509795579) /* sqrt(2) * (c7-c5) */ +
z2 * (-REDUCED_FIX_0_601344887) /* sqrt(2) * (c5-c1) */ +
z3 * REDUCED_FIX_0_899976223 /* sqrt(2) * (c3-c7) */ +
z4 * REDUCED_FIX_2_562915447; /* sqrt(2) * (c1+c3) */
/* Final output stage */
m_componentBuffer[currentOutRow][output_col + 0] = limit[limitOffset + JpegUtils.DESCALE(tmp10 + tmp2, REDUCED_CONST_BITS + REDUCED_PASS1_BITS + 3 + 1) & RANGE_MASK];
m_componentBuffer[currentOutRow][output_col + 3] = limit[limitOffset + JpegUtils.DESCALE(tmp10 - tmp2, REDUCED_CONST_BITS + REDUCED_PASS1_BITS + 3 + 1) & RANGE_MASK];
m_componentBuffer[currentOutRow][output_col + 1] = limit[limitOffset + JpegUtils.DESCALE(tmp12 + tmp0, REDUCED_CONST_BITS + REDUCED_PASS1_BITS + 3 + 1) & RANGE_MASK];
m_componentBuffer[currentOutRow][output_col + 2] = limit[limitOffset + JpegUtils.DESCALE(tmp12 - tmp0, REDUCED_CONST_BITS + REDUCED_PASS1_BITS + 3 + 1) & RANGE_MASK];
workspaceIndex += JpegConstants.DCTSIZE; /* advance pointer to next row */
}
}