package org.jcodec.common.dct;
import static java.lang.Math.PI;
import static java.lang.Math.cos;
import static java.lang.Math.sqrt;
/**
* This class is part of JCodec ( www.jcodec.org )
* This software is distributed under FreeBSD License
*
* @author The JCodec project
*
*/
public class SimpleIDCT10Bit {
public static int W1 = 90901;
public static int W2 = 85627;
public static int W3 = 77062;
public static int W4 = 65535;
public static int W5 = 51491;
public static int W6 = 35468;
public static int W7 = 18081;
public static int ROW_SHIFT = 15;
public static int COL_SHIFT = 20;
public static final void idct10(int[] buf, int off) {
for (int i = 0; i < 8; i++)
idctRow(buf, off + (i << 3));
for (int i = 0; i < 8; i++)
idctCol(buf, off + i);
}
private static final void idctCol(int[] buf, int off) {
int a0, a1, a2, a3, b0, b1, b2, b3;
a0 = W4 * (buf[off + 8 * 0] + ((1 << (COL_SHIFT - 1)) / W4));
a1 = a0;
a2 = a0;
a3 = a0;
a0 += W2 * buf[off + 8 * 2];
a1 += W6 * buf[off + 8 * 2];
a2 += -W6 * buf[off + 8 * 2];
a3 += -W2 * buf[off + 8 * 2];
b0 = W1 * buf[off + 8 * 1];
b1 = W3 * buf[off + 8 * 1];
b2 = W5 * buf[off + 8 * 1];
b3 = W7 * buf[off + 8 * 1];
b0 += W3 * buf[off + 8 * 3];
b1 += -W7 * buf[off + 8 * 3];
b2 += -W1 * buf[off + 8 * 3];
b3 += -W5 * buf[off + 8 * 3];
if (buf[off + 8 * 4] != 0) {
a0 += W4 * buf[off + 8 * 4];
a1 += -W4 * buf[off + 8 * 4];
a2 += -W4 * buf[off + 8 * 4];
a3 += W4 * buf[off + 8 * 4];
}
if (buf[off + 8 * 5] != 0) {
b0 += W5 * buf[off + 8 * 5];
b1 += -W1 * buf[off + 8 * 5];
b2 += W7 * buf[off + 8 * 5];
b3 += W3 * buf[off + 8 * 5];
}
if (buf[off + 8 * 6] != 0) {
a0 += W6 * buf[off + 8 * 6];
a1 += -W2 * buf[off + 8 * 6];
a2 += W2 * buf[off + 8 * 6];
a3 += -W6 * buf[off + 8 * 6];
}
if (buf[off + 8 * 7] != 0) {
b0 += W7 * buf[off + 8 * 7];
b1 += -W5 * buf[off + 8 * 7];
b2 += W3 * buf[off + 8 * 7];
b3 += -W1 * buf[off + 8 * 7];
}
buf[off] = ((a0 + b0) >> COL_SHIFT);
buf[off + 8] = ((a1 + b1) >> COL_SHIFT);
buf[off + 16] = ((a2 + b2) >> COL_SHIFT);
buf[off + 24] = ((a3 + b3) >> COL_SHIFT);
buf[off + 32] = ((a3 - b3) >> COL_SHIFT);
buf[off + 40] = ((a2 - b2) >> COL_SHIFT);
buf[off + 48] = ((a1 - b1) >> COL_SHIFT);
buf[off + 56] = ((a0 - b0) >> COL_SHIFT);
}
private static final void idctRow(int[] buf, int off) {
int a0, a1, a2, a3, b0, b1, b2, b3;
a0 = (W4 * buf[off]) + (1 << (ROW_SHIFT - 1));
a1 = a0;
a2 = a0;
a3 = a0;
a0 += W2 * buf[off + 2];
a1 += W6 * buf[off + 2];
a2 -= W6 * buf[off + 2];
a3 -= W2 * buf[off + 2];
b0 = W1 * buf[off + 1];
b0 += W3 * buf[off + 3];
b1 = W3 * buf[off + 1];
b1 += -W7 * buf[off + 3];
b2 = W5 * buf[off + 1];
b2 += -W1 * buf[off + 3];
b3 = W7 * buf[off + 1];
b3 += -W5 * buf[off + 3];
if (buf[off + 4] != 0 || buf[off + 5] != 0 || buf[off + 6] != 0 || buf[off + 7] != 0) {
a0 += W4 * buf[off + 4] + W6 * buf[off + 6];
a1 += -W4 * buf[off + 4] - W2 * buf[off + 6];
a2 += -W4 * buf[off + 4] + W2 * buf[off + 6];
a3 += W4 * buf[off + 4] - W6 * buf[off + 6];
b0 += W5 * buf[off + 5];
b0 += W7 * buf[off + 7];
b1 += -W1 * buf[off + 5];
b1 += -W5 * buf[off + 7];
b2 += W7 * buf[off + 5];
b2 += W3 * buf[off + 7];
b3 += W3 * buf[off + 5];
b3 += -W1 * buf[off + 7];
}
buf[off + 0] = (a0 + b0) >> ROW_SHIFT;
buf[off + 7] = (a0 - b0) >> ROW_SHIFT;
buf[off + 1] = (a1 + b1) >> ROW_SHIFT;
buf[off + 6] = (a1 - b1) >> ROW_SHIFT;
buf[off + 2] = (a2 + b2) >> ROW_SHIFT;
buf[off + 5] = (a2 - b2) >> ROW_SHIFT;
buf[off + 3] = (a3 + b3) >> ROW_SHIFT;
buf[off + 4] = (a3 - b3) >> ROW_SHIFT;
}
static double[] coefficients = new double[64];
static {
for (int j = 0; j < 8; ++j) {
coefficients[j] = sqrt(0.125);
for (int i = 8; i < 64; i += 8) {
coefficients[i + j] = 0.5 * cos(i * (j + 0.5) * PI / 64.0);
}
}
}
// TODO: integer implementation of this
public static void fdct10(byte[] block, int off, int[] dctOut) {
int i, j, k;
double[] out = new double[8 * 8];
for (i = 0; i < 64; i += 8) {
for (j = 0; j < 8; ++j) {
double tmp = 0;
for (k = 0; k < 8; ++k) {
tmp += coefficients[i + k] * ((block[k * 8 + j + off] + 128) << 2);
}
out[i + j] = tmp * 4;
}
}
for (j = 0; j < 8; ++j) {
for (i = 0; i < 64; i += 8) {
double tmp = 0;
for (k = 0; k < 8; ++k) {
tmp += out[i + k] * coefficients[j * 8 + k];
}
dctOut[i + j + off] = (int) (tmp + 0.499999999999);
}
}
}
}