import java.lang.*;
import java.util.*;
import java.io.*;
/**
* <h3><b>DCT - A Java implementation of the Discreet Cosine Transform</b></h3><br><br>
* <hr>
* The discreet cosine transform converts spatial information to "frequency" or
* spectral information, with the X and Y axes representing frequencies of the
* signal in different dimensions. This allows for "lossy" compression of image
* data by determining which information can be thrown away without compromising
* the image.<br><br>
* The DCT is used in many compression and transmission codecs, such as JPEG, MPEG
* and others. The pixels when transformed are arraged from the most signifigant pixel
* to the least signifigant pixel. The DCT functions themselves are lossless.
* Pixel loss occurs when the least signifigant pixels are quantitized to 0.
* <br><br>
* This is NOT a JPEG or JFIF compliant implementation however it could
* be with very little extra work. (i.e. A huffman encoding stage needs
* to be added.) I am making this source availible in the hopes that
* someone will add this functionality to the class, if you do, please
* email me! As always, if you have any problems feel free to contact
* me. (Or comments, or praise, etc..)
* <br><br>
* <b>Keep in mind</b> that when compressing color images with this, you will
* need to break the image up into it's R G B components and preform
* the calculations three times!!
* <br><br>
* <b>A general algorithim for DCT compression with this class:</b> <br><br>
* 1) Create a DCT Object.<br>
* 2) Set up your program to read pixel information in 8*8 blocks. See example.<br>
* 3) Run the forwardDCT() on all blocks.<br>
* 4) Run the quantitizeImage() on all blocks.<br>
* 5) If you want, send the information to the imageCompressor().<br><br>
* <b>A general algorithim for DCT decompression with this class:</b> <br><br>
* 1) Create a DCT Object. <br>
* 2) Set up the program to convert compressed data in 8*8 blocks. (if compressed)<br>
* 3) Run the data through dequantitizeImage(). <br>
* 4) Run the data through inverseDCT().<br>
* <br><br>
* A complete implementation of an image compressor which compares
* the quality of the two images is also availible. See the
* JEncode/Decode <a href="JEncode.java">source code.</a> The
* <a href="DCT.java">DCT.java source code</a> is also availible.
* The implementation is also handy for seeing how to break the image
* down, read in 8x8 blocks, and reconstruct it. The <a href="steve.jpg">
* sample graphic</a> is handy to have too. (Bad pic of me)
* The best way to get ahold of me is through my
* <a href="http://eagle.uccb.ns.ca/steve/home.html">homepage</a>. There's
* lots of goodies there too.
* @version 1.0.1 August 22nd 1996
* @author <a href="http://eagle.uccb.ns.ca/steve/home.html">Stephen Manley</a> - [email protected]
*/
// <pre>
public class DCT
{
/**
* DCT Block Size - default 8
*/
public int N = 8;
/**
* Image Quality (0-25) - default 25 (worst image / best compression)
*/
public int QUALITY = 25;
/**
* Image width - must correspond to imageArray bounds - default 320
*/
public int ROWS = 320;
/**
* Image height - must correspond to imageArray bounds - default 200
*/
public int COLS = 240;
/**
* The ZigZag matrix.
*/
public int zigZag[][] = new int[64][2];
/**
* Cosine matrix. N * N.
*/
public double c[][] = new double[N][N];
/**
* Transformed cosine matrix, N*N.
*/
public double cT[][] = new double[N][N];
/**
* Quantitization Matrix.
*/
public int quantum[][] = new int[N][N];
/**
* DCT Result Matrix
*/
public int resultDCT[][] = new int[ROWS][COLS];
/**
* Constructs a new DCT object. Initializes the cosine transform matrix
* these are used when computing the DCT and it's inverse. This also
* initializes the run length counters and the ZigZag sequence. Note that
* the image quality can be worse than 25 however the image will be
* extemely pixelated, usually to a block size of N.
*
* @param QUALITY The quality of the image (0 best - 25 worst)
*
*/
public DCT(int QUALITY)
{
initZigZag();
initMatrix(QUALITY);
}
/**
* This method sets up the quantization matrix using the Quality parameter
* and then sets up the Cosine Transform Matrix and the Transposed CT.
* These are used by the forward and inverse DCT. The RLE encoding
* variables are set up to track the number of consecutive zero values
* that have output or will be input.
* @param quality The quality scaling factor
*/
private void initMatrix(int quality)
{
int i;
int j;
for (i = 0; i < N; i++)
{
for (j = 0; j < N; j++)
{
quantum[i][j] = (1 + ((1 + i + j) * quality));
}
}
for (j = 0; j < N; j++)
{
double nn = (double)(N);
c[0][j] = 1.0 / Math.sqrt(nn);
cT[j][0] = c[0][j];
}
for (i = 1; i < 8; i++)
{
for (j = 0; j < 8; j++)
{
double jj = (double)j;
double ii = (double)i;
c[i][j] = Math.sqrt(2.0/8.0) * Math.cos(((2.0 * jj + 1.0) * ii * Math.PI) / (2.0 * 8.0));
cT[j][i] = c[i][j];
}
}
}
/**
* Initializes the ZigZag matrix.
*/
private void initZigZag()
{
zigZag[0][0] = 0; // 0,0
zigZag[0][1] = 0;
zigZag[1][0] = 0; // 0,1
zigZag[1][1] = 1;
zigZag[2][0] = 1; // 1,0
zigZag[2][1] = 0;
zigZag[3][0] = 2; // 2,0
zigZag[3][1] = 0;
zigZag[4][0] = 1; // 1,1
zigZag[4][1] = 1;
zigZag[5][0] = 0; // 0,2
zigZag[5][1] = 2;
zigZag[6][0] = 0; // 0,3
zigZag[6][1] = 3;
zigZag[7][0] = 1; // 1,2
zigZag[7][1] = 2;
zigZag[8][0] = 2; // 2,1
zigZag[8][1] = 1;
zigZag[9][0] = 3; // 3,0
zigZag[9][1] = 0;
zigZag[10][0] = 4; // 4,0
zigZag[10][1] = 0;
zigZag[11][0] = 3; // 3,1
zigZag[11][1] = 1;
zigZag[12][0] = 2; // 2,2
zigZag[12][1] = 2;
zigZag[13][0] = 1; // 1,3
zigZag[13][1] = 3;
zigZag[14][0] = 0; // 0,4
zigZag[14][1] = 4;
zigZag[15][0] = 0; // 0,5
zigZag[15][1] = 5;
zigZag[16][0] = 1; // 1,4
zigZag[16][1] = 4;
zigZag[17][0] = 2; // 2,3
zigZag[17][1] = 3;
zigZag[18][0] = 3; // 3,2
zigZag[18][1] = 2;
zigZag[19][0] = 4; // 4,1
zigZag[19][1] = 1;
zigZag[20][0] = 5; // 5,0
zigZag[20][1] = 0;
zigZag[21][0] = 6; // 6,0
zigZag[21][1] = 0;
zigZag[22][0] = 5; // 5,1
zigZag[22][1] = 1;
zigZag[23][0] = 4; // 4,2
zigZag[23][1] = 2;
zigZag[24][0] = 3; // 3,3
zigZag[24][1] = 3;
zigZag[25][0] = 2; // 2,4
zigZag[25][1] = 4;
zigZag[26][0] = 1; // 1,5
zigZag[26][1] = 5;
zigZag[27][0] = 0; // 0,6
zigZag[27][1] = 6;
zigZag[28][0] = 0; // 0,7
zigZag[28][1] = 7;
zigZag[29][0] = 1; // 1,6
zigZag[29][1] = 6;
zigZag[30][0] = 2; // 2,5
zigZag[30][1] = 5;
zigZag[31][0] = 3; // 3,4
zigZag[31][1] = 4;
zigZag[32][0] = 4; // 4,3
zigZag[32][1] = 3;
zigZag[33][0] = 5; // 5,2
zigZag[33][1] = 2;
zigZag[34][0] = 6; // 6,1
zigZag[34][1] = 1;
zigZag[35][0]