// Author: Ooi Wei Tsang // vim:ts=4:sw=4 import java.awt.*; import java.awt.image.*; import java.awt.event.*; import javax.swing.*; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; public class DCTdemo extends JApplet { Point point_; BufferedImage bi_; BufferedImage block_; Rectangle largePixels_[][]; Rectangle largeDCTs_[][]; Rectangle zigzagBar_[] = new Rectangle[64]; Color colors_[][]; Color dct_[][]; static final int zz[] = { 0, 1, 5, 6, 14, 15, 27, 28, 2, 4, 7, 13, 16, 26, 29, 42, 3, 8, 12, 17, 25, 30, 41, 43, 9, 11, 18, 24, 31, 40, 44, 53, 10, 19, 23, 32, 39, 45, 52, 54, 20, 22, 33, 38, 46, 51, 55, 60, 21, 34, 37, 47, 50, 56, 59, 61, 35, 36, 48, 49, 57, 58, 62, 63}; double zigzag_[] = new double[64]; double cos_table_[][]; int dctElements[][] = { {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, {1,1,1,1,1,1,1,1}, }; static final int w_ = 200; static final int h_ = 200; static final int origX_ = 10; static final int origY_ = 10; static final int blockX_ = 220; static final int blockY_ = 10; static final int dctX_ = 430; static final int dctY_ = 10; static final int zigzagX_ = 10; static final int zigzagY_ = 430; static final int zigzagWidth_ = 8; public void init() { setBackground(Color.white); initLargePixelsAndColors(); initDCT(); bi_ = loadImage(); } private void initDCT() { cos_table_ = new double[8][8]; for (int v = 0; v < 8; v++) for (int y = 0; y < 8; y++) cos_table_[v][y] = Math.cos ( ((double)(2*y+1) * (double)(v) * (Math.PI/16.0))); } private void initLargePixelsAndColors() { largePixels_ = new Rectangle[8][8]; colors_ = new Color[8][8]; largeDCTs_ = new Rectangle[8][8]; dct_ = new Color[8][8]; for (int i = 0; i < 8; i++) for (int j = 0; j < 8; j++) { largePixels_[i][j] = new Rectangle(blockX_ + 25*i, blockY_ + 25*j, 25, 25); largeDCTs_[i][j] = new Rectangle(dctX_ + 25*i, dctY_ + 25*j, 25, 25); colors_[i][j] = Color.green; dct_[i][j] = Color.green; } for (int i = 0; i < 64; i++) zigzagBar_[i] = new Rectangle(0,0,0,0); } private BufferedImage loadImage() { Image img = getImage(getDocumentBase(), "DCTdemo.jpg"); try { MediaTracker tracker = new MediaTracker(this); tracker.addImage(img, 0); tracker.waitForID(0); } catch (Exception e) { } int w = img.getWidth(this); int h = img.getHeight(this); BufferedImage result = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics2D g2d = result.createGraphics(); g2d.drawImage(img, 0, 0, this); // add event listening addMouseMotionListener(new MyMouseAdapter()); return result; } private void loadBlock(int x, int y) { for (int i = 0; i < 8; i++) for (int j = 0; j < 8; j++) { colors_[i][j] = new Color(bi_.getRGB(x - origX_ + i, y - origY_ + j)); } calcDCT(); } public void paint(Graphics g) { Graphics2D g2 = (Graphics2D) g; g2.drawImage(bi_,origX_,origY_,this); for (int i = 0; i < 8; i++) for (int j = 0; j < 8; j++) { g2.setColor(colors_[i][j]); g2.fill(largePixels_[i][j]); g2.setColor(dct_[i][j]); g2.fill(largeDCTs_[i][j]); g2.setColor(Color.green); g2.draw(largePixels_[i][j]); g2.draw(largeDCTs_[i][j]); } for (int i = 0; i < 64; i++) { g2.setColor(Color.white); g2.fill(zigzagBar_[i]); if (zigzag_[i] > 0) { zigzagBar_[i].setLocation( (int) Math.round(zigzagX_ + (zigzagWidth_+1)*i - 0.5), (int) Math.round(zigzagY_ - zigzag_[i]/8 - 0.5)); } else { zigzagBar_[i].setLocation( (int) Math.round(zigzagX_ + (zigzagWidth_+1)*i - 0.5), (int) Math.round(zigzagY_ - 0.5)); } zigzagBar_[i].setSize( (int) Math.round(zigzagWidth_ - 0.5), (int) Math.round(Math.abs(zigzag_[i])/8 - 0.5)); g2.setColor(new Color(44, 15, 229)); g2.fill(zigzagBar_[i]); } g2.setColor(Color.black); g2.drawLine(zigzagX_, zigzagY_ - 1, zigzagX_ + (zigzagWidth_+1)*64, zigzagY_-1); } class MyMouseAdapter extends MouseMotionAdapter { public void mouseMoved(MouseEvent event) { point_ = event.getPoint(); int x = point_.x; int y = point_.y; if (x > origX_ && x < origX_ + w_ - 8 && y > origY_ && y < origY_ + h_ - 8) { loadBlock(x, y); repaint(); } } } void calcDCT() { int y[][] = new int[8][8]; for (int i = 0; i < 8; i++) for (int j = 0; j < 8; j++) { y[i][j] = (int)(0.257*colors_[i][j].getRed () + 0.504*colors_[i][j].getGreen () + 0.098*colors_[i][j].getBlue () + 16); } dct(y); for (int i = 0; i < 8; i++) for (int j = 0; j < 8; j++) dct_[i][j] = new Color (y[i][j], y[i][j], y[i][j]); } void dct (int[][] block) { double temp[][] = new double[8][8]; double sum; for (int u = 0; u < 8; u++) for (int v = 0; v < 8; v++) { sum = 0.0; for (int x = 0; x < 8; x++) for (int y = 0; y < 8; y++) sum += block[x][y] * cos_table_[u][x]*cos_table_[v][y]; temp[u][v] = 0.25 * C(u, v) * sum; } int zzIndex = 0; for (int u = 0; u < 8; u++) for (int v = 0; v < 8; v++) { zigzag_[zz[zzIndex++]] = temp[u][v]; block[u][v] = (int)(Math.abs(temp[u][v])/8); if (block[u][v] < 0) block[u][v] = 0; if (block[u][v] > 255) block[u][v] = 255; } } double C(int u, int v) { if (u == 0 && v == 0) return 0.5; else if (u == 0 || v == 0) return (1.0 / Math.sqrt (2.0)); else return 1.0; } }