/**
* MediaFrame is an Open Source streaming media platform in Java
* which provides a fast, easy to implement and extremely small applet
* that enables to view your audio/video content without having
* to rely on external player applications or bulky plug-ins.
*
* Copyright (C) 2004/5 MediaFrame (http://www.mediaframe.org).
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
package mediaframe.mpeg4.video;
/**
* IDFT
*/
public class IDFT {
public final static int SHIFT_BITS = 12;
private int pixels_per_line;
private long[][] coeff = new long[8][8];
private long[][] tmp = new long[8][8];
public final long C2 = (long) ((1 << SHIFT_BITS) * 2d * Math
.cos(Math.PI / 8d));
public final long C4 = (long) ((1 << SHIFT_BITS) * Math.sqrt(2d));
public final long C6 = (long) ((1 << SHIFT_BITS) * 2d * Math
.sin(Math.PI / 8d));
public final long Q = C2 - C6;
public final long R = C2 + C6;
public IDFT(int pixels_per_line) {
super();
this.pixels_per_line = pixels_per_line;
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
// calculates the (4 / Cu) * cos(PI * u / 16) values
double k = 4d;
if ((i == 0) && (j == 0)) {
k = 8d;
} else if ((i == 0) || (j == 0)) {
k = 8d / Math.sqrt(2d);
}
coeff[i][j] = (long) ((1 << SHIFT_BITS) * ((Math
.cos((Math.PI * (double) i) / 16d))
* Math.cos((Math.PI * (double) j) / 16d) / k));
}
}
}
private long a2, a4, a5, a6, tmp1, tmp2;
private long b0, b1, b2, b3, b5, b6, b7, tmp4;
private long tmp3, n0, n1, n2, n3, n5, n6;
private long m0, m1, m2, m3, m4, m5, m6, m7;
public void idft_line(long[][] block, int index,
boolean horizontal_direction) {
if (horizontal_direction) {
b0 = block[index][0] >> 4;
b1 = block[index][4] >> 3;
a2 = (block[index][2] >> 3) - (block[index][6] >> 3);
n6 = b3 = (block[index][2] >> 3) + (block[index][6] >> 3);
a4 = (block[index][5] >> 3) - (block[index][3] >> 3);
tmp1 = (block[index][1] >> 3) + (block[index][7] >> 3);
tmp2 = (block[index][3] >> 3) + (block[index][5] >> 3);
a6 = (block[index][1] >> 3) - (block[index][7] >> 3);
} else {
b0 = block[0][index] >> 4;
b1 = block[4][index] >> 3;
a2 = (block[2][index] >> 3) - (block[6][index] >> 3);
n6 = b3 = (block[2][index] >> 3) + (block[6][index] >> 3);
a4 = (block[5][index] >> 3) - (block[3][index] >> 3);
tmp1 = (block[1][index] >> 3) + (block[7][index] >> 3);
tmp2 = (block[3][index] >> 3) + (block[5][index] >> 3);
a6 = (block[1][index] >> 3) - (block[7][index] >> 3);
}
a5 = tmp1 - tmp2;
m0 = b7 = tmp1 + tmp2;
b2 = (C4 * a2) >> SHIFT_BITS;
tmp4 = (C6 * (a4 + a6)) >> SHIFT_BITS;
n5 = ((-Q * a4) >> SHIFT_BITS) - tmp4;
b5 = (C4 * a5) >> SHIFT_BITS;
b6 = ((R * a6) >> SHIFT_BITS) - tmp4;
tmp3 = b6 - b7;
m1 = n0 = tmp3 - b5;
n1 = b0 - b1;
n2 = b2 - b3;
n3 = b0 + b1;
m2 = tmp3;
m3 = n1 + n2;
m4 = n3 + n6;
m5 = n1 - n2;
m6 = n3 - n6;
m7 = n5 - n0;
if (horizontal_direction) {
block[index][0] = m4 + m0;
block[index][1] = m3 + m2;
block[index][2] = m5 - m1;
block[index][3] = m6 - m7;
block[index][4] = m6 + m7;
block[index][5] = m5 + m1;
block[index][6] = m3 - m2;
block[index][7] = m4 - m0;
} else {
block[0][index] = m4 + m0;
block[1][index] = m3 + m2;
block[2][index] = m5 - m1;
block[3][index] = m6 - m7;
block[4][index] = m6 + m7;
block[5][index] = m5 + m1;
block[6][index] = m3 - m2;
block[7][index] = m4 - m0;
}
}
public void idft(int[][] block, int[] pixel_data, int block_pointer) {
int i, j;
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
tmp[i][j] = block[i][j] * coeff[i][j];
}
}
for (i = 0; i < 8; i++) {
idft_line(tmp, i, true);
}
for (i = 0; i < 8; i++) {
idft_line(tmp, i, false);
}
for (i = 0; i < 8; i++) {
for (j = 0; j < 8; j++) {
pixel_data[block_pointer + j] = (int) ((tmp[i][j]) >> (SHIFT_BITS));
}
block_pointer += pixels_per_line;
}
}
}