package wcet.mrtc;
/**
* Forward Discrete Cosine Transform. Used on 8x8 image blocks to reassemble blocks
* in order to ease quantization compressing image information on the more
* significant frequency components.
*
* Expected Result:
* block = { 699,164,-51,-16, 31,-15,-19, 8,
* 71, 14,-61, -2,-11,-12, 7, 12,
* -58,-55, 13, 28,-20, -7, 14,-18,
* 29, 22, 3, 3,-11, 7, 11,-22,
* -1,-28,-27, 10, 0, -7, 11, 6,
* 7, 6, 21, 21,-10, -8, 2,-14,
* 1, -7,-15,-15,-10, 15, 16,-10,
* 0, -1, 0, 15, 4,-13, -5, 4 };
*
* Hexadecimal result:
* block = 02bb00a4 ffcdfff0 001ffff1 ffed0008 0047000e ffc3fffe 000bfff4 0007000c
* ffc6ffc9 000d001c ffecfff9 000effee 001d0016 00030003 fff50007 000bffea
* ffffffe4 ffe5000a 0000fff9 000b0006 00070006 00150015 fff6fff8 0002fff2
* 0001fff9 fff1fff1 fff6000f 0010fff6 0000ffff 0000000f 0004fff3 fffb0004
*
* WCET aspect: A lot of calculations based on integer array elements.
*
* Ported from C code written by Jan Gustafsson for the <a
* href="http://www.mrtc.mdh.se/projects/wcet/benchmarks.html">Maelardalen WCET
* Benchmarks</a>.
*/
public class DiscreteCosineTransform
{
// Cosine Transform Coefficients
private static final int W1 = 2841; // 2048*sqrt(2)*cos(1*pi/16)
private static final int W2 = 2676; // 2048*sqrt(2)*cos(2*pi/16)
private static final int W3 = 2408; // 2048*sqrt(2)*cos(3*pi/16)
private static final int W5 = 1609; // 2048*sqrt(2)*cos(5*pi/16)
private static final int W6 = 1108; // 2048*sqrt(2)*cos(6*pi/16)
private static final int W7 = 565; // 2048*sqrt(2)*cos(7*pi/16)
// Other FDCT Parameters
private static final int CONST_BITS = 13;
private static final int PASS1_BITS = 2;
// Image block to be transformed
public int[][] block = {
{ 99, 104, 109, 113, 115, 115, 55, 55 },
{ 104, 111, 113, 116, 119, 56, 56, 56 },
{ 110, 115, 120, 119, 118, 56, 56, 56 },
{ 119, 121, 122, 120, 120, 59, 59, 59 },
{ 119, 120, 121, 122, 122, 55, 55, 55 },
{ 121, 121, 121, 121, 60, 57, 57, 57 },
{ 122, 122, 61, 63, 62, 57, 57, 57 },
{ 62, 62, 61, 61, 63, 58, 58, 58 }
};
public void fdct(int[][] block, int lx)
{
int tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7;
int tmp10, tmp11, tmp12, tmp13;
int z1, z2, z3, z4, z5;
int constant;
// Pass 1: process rows.
// Note that results are scaled up by sqrt(8) compared to a true DCT;
// furthermore, we scale the results by 2**PASS1_BITS.
//@LoopBound(max=8)
for (int i = 0; i < 8; i++) // @WCA loop=8
{
tmp0 = block[i][0] + block[i][7];
tmp7 = block[i][0] - block[i][7];
tmp1 = block[i][1] + block[i][6];
tmp6 = block[i][1] - block[i][6];
tmp2 = block[i][2] + block[i][5];
tmp5 = block[i][2] - block[i][5];
tmp3 = block[i][3] + block[i][4];
tmp4 = block[i][3] - block[i][4];
// Even part per LL&M figure 1 --- note that published figure
// is faulty; rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
block[i][0] = ((tmp10 + tmp11) << PASS1_BITS);
block[i][4] = ((tmp10 - tmp11) << PASS1_BITS);
constant = 4433;
z1 = (tmp12 + tmp13) * constant;
constant = 6270;
block[i][2] = (z1 + (tmp13 * constant)) >> (CONST_BITS - PASS1_BITS);
constant = -15137;
block[i][6] = (z1 + (tmp12 * constant)) >> (CONST_BITS - PASS1_BITS);
// Odd part per figure 8 --- note paper omits factor of
// sqrt(2). cK represents cos(K*pi/16). i0..i3 in the paper
// are tmp4..tmp7 here.
z1 = tmp4 + tmp7;
z2 = tmp5 + tmp6;
z3 = tmp4 + tmp6;
z4 = tmp5 + tmp7;
constant = 9633;
z5 = ((z3 + z4) * constant); // sqrt(2) * c3
constant = 2446;
tmp4 = (tmp4 * constant); // sqrt(2) * (-c1+c3+c5-c7)
constant = 16819;
tmp5 = (tmp5 * constant); // sqrt(2) * ( c1+c3-c5+c7)
constant = 25172;
tmp6 = (tmp6 * constant); // sqrt(2) * ( c1+c3+c5-c7)
constant = 12299;
tmp7 = (tmp7 * constant); // sqrt(2) * ( c1+c3-c5-c7)
constant = -7373;
z1 = (z1 * constant); // sqrt(2) * (c7-c3)
constant = -20995;
z2 = (z2 * constant); // sqrt(2) * (-c1-c3)
constant = -16069;
z3 = (z3 * constant); // sqrt(2) * (-c3-c5)
constant = -3196;
z4 = (z4 * constant); // sqrt(2) * (c5-c3)
z3 += z5;
z4 += z5;
block[i][7] = (tmp4 + z1 + z3) >> (CONST_BITS - PASS1_BITS);
block[i][5] = (tmp5 + z2 + z4) >> (CONST_BITS - PASS1_BITS);
block[i][3] = (tmp6 + z2 + z3) >> (CONST_BITS - PASS1_BITS);
block[i][1] = (tmp7 + z1 + z4) >> (CONST_BITS - PASS1_BITS);
}
// Pass 2: process columns.
//@LoopBound(max=8)
for (int i = 0; i < 8; i++) // @WCA loop=8
{
tmp0 = block[0][i] + block[7][i];
tmp7 = block[0][i] - block[7][i];
tmp1 = block[1][i] + block[6][i];
tmp6 = block[1][i] - block[6][i];
tmp2 = block[2][i] + block[5][i];
tmp5 = block[2][i] - block[5][i];
tmp3 = block[3][i] + block[4][i];
tmp4 = block[3][i] - block[4][i];
// Even part per LL&M figure 1 --- note that published figure
// is faulty; rotator "sqrt(2)*c1" should be "sqrt(2)*c6".
tmp10 = tmp0 + tmp3;
tmp13 = tmp0 - tmp3;
tmp11 = tmp1 + tmp2;
tmp12 = tmp1 - tmp2;
block[0][i] = (tmp10 + tmp11) >> (PASS1_BITS + 3);
block[4][i] = (tmp10 - tmp11) >> (PASS1_BITS + 3);
constant = 4433;
z1 = ((tmp12 + tmp13) * constant);
constant = 6270;
block[2][i] = (z1 + (tmp13 * constant)) >> (CONST_BITS + PASS1_BITS + 3);
constant = -15137;
block[6][i] = (z1 + (tmp12 * constant)) >> (CONST_BITS + PASS1_BITS + 3);
// Odd part per figure 8 --- note paper omits factor of
// sqrt(2). cK represents cos(K*pi/16). i0..i3 in the paper
// are tmp4..tmp7 here.
z1 = tmp4 + tmp7;
z2 = tmp5 + tmp6;
z3 = tmp4 + tmp6;
z4 = tmp5 + tmp7;
constant = 9633;
z5 = ((z3 + z4) * constant); // sqrt(2) * c3
constant = 2446;
tmp4 = (tmp4 * constant); // sqrt(2) * (-c1+c3+c5-c7)
constant = 16819;
tmp5 = (tmp5 * constant); // sqrt(2) * ( c1+c3-c5+c7)
constant = 25172;
tmp6 = (tmp6 * constant); // sqrt(2) * ( c1+c3+c5-c7)
constant = 12299;
tmp7 = (tmp7 * constant); // sqrt(2) * ( c1+c3-c5-c7)
constant = -7373;
z1 = (z1 * constant); // sqrt(2) * (c7-c3)
constant = -20995;
z2 = (z2 * constant); // sqrt(2) * (-c1-c3)
constant = -16069;
z3 = (z3 * constant); // sqrt(2) * (-c3-c5)
constant = -3196;
z4 = (z4 * constant); // sqrt(2) * (c5-c3)
z3 += z5;
z4 += z5;
block[7][i] = (tmp4 + z1 + z3) >> (CONST_BITS + PASS1_BITS + 3);
block[5][i] = (tmp5 + z2 + z4) >> (CONST_BITS + PASS1_BITS + 3);
block[3][i] = (tmp6 + z2 + z3) >> (CONST_BITS + PASS1_BITS + 3);
block[1][i] = (tmp7 + z1 + z4) >> (CONST_BITS + PASS1_BITS + 3);
}
}
public static void main(String[] args)
{
DiscreteCosineTransform d = new DiscreteCosineTransform();
// x8 Blocks, DC precision value = 0,
// Quantization coefficient (mquant) = 64
d.fdct(d.block, 8);
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 8; j++)
{
System.out.println(d.block[i][j] + " ");
}
System.out.println();
}
}
}