import java.applet.*; import java.awt.*; import java.awt.image.*; import java.awt.event.*; import java.net.URL; import Jama.*; public class SVD extends Applet implements KeyListener { private ImageCanvas canvas; private Image image; private int w, h, r; private SingularValueDecomposition svd; public void init() { System.err.println("Loading image boat.gif"); image = getImg("boat.gif"); w = image.getWidth(this); h = image.getHeight(this); r = w; System.err.println("Computing svd"); svd = getSVD(image); System.err.println("Drawing canvas"); canvas = new ImageCanvas(image); canvas.setRank(r); canvas.addKeyListener(this); add(canvas); System.err.println("Ready: play with the four arrow keys"); } public SingularValueDecomposition getSVD(Image img) { int pixels[] = extractPixelValues(img); Matrix m = new Matrix(int2double(pixels), h); SingularValueDecomposition svd = m.svd(); return svd; } public void updateImage() { Matrix U = svd.getU(); Matrix V = svd.getV(); Matrix S = svd.getS(); for (int k = r; k < w; k++) S.set(k, k, 0); Matrix A = U.times(S.times(V.transpose())); double a[] = A.getColumnPackedCopy(); image = createImage(double2int(a), w, h); canvas.setRank(r); canvas.setImage(image); } public void keyPressed(KeyEvent e) { if (e.getKeyCode() == e.VK_UP) { if (r <= w/2) r *= 2; } else if (e.getKeyCode() == e.VK_DOWN) { if (r >= 2) r /= 2; } else if (e.getKeyCode() == e.VK_LEFT) { if (r >= 2) r--; } else if (e.getKeyCode() == e.VK_RIGHT) { if (r < w) r++; } updateImage(); } public void keyReleased(KeyEvent e) {} public void keyTyped(KeyEvent e) {} public Image getImg(String fname) { Image img = null; System.err.println("CodeBase: " + getCodeBase()); System.err.println("Resource: " + getClass().getResource(fname)); try { // img = getImage(getCodeBase(), fname); img = getImage(getClass().getResource(fname)); waitForImage(img); } catch(Exception e) { System.err.println("Could not get image"); } return img; } public void waitForImage(Image i) { MediaTracker tracker = new MediaTracker(this); try { tracker.addImage(i,0); tracker.waitForID(0); } catch(InterruptedException e) {System.err.println("Wait interrupted.");} } public int[] extractPixelValues(Image image) { int width = image.getWidth(this), height = image.getHeight(this); int pixels[] = new int[width * height]; PixelGrabber grabber = new PixelGrabber(image, 0, 0, width, height, pixels, 0, width); try { boolean result = grabber.grabPixels(60000); //bug in PixelGrabber? if (!result) { System.err.println("Could not grab pixels from image before quantum"+ " expired."); return pixels; } } catch (InterruptedException e) {System.err.println("Grab interrupted.");} //each pixel value is of the form alpha, red, green, blue, so we must //keep only the last 8 bits to make it fall between 0 and 255. for (int k = 0; k < pixels.length; k++) pixels[k] &= 255; return pixels; } public Image createImage(int pixels[], int width, int height) { int newpixels[] = new int[pixels.length]; for (int k = 0; k < pixels.length; k++) { int a = pixels[k]; newpixels[k] = (255 << 24) | (a << 16) | (a << 8) | a; } Image i = createImage(new MemoryImageSource(width, height, newpixels, 0, width)); return i; } public double[] int2double(int a[]) { double d[] = new double[a.length]; for (int k = 0; k < a.length; k++) d[k] = (double) a[k]; return d; } public int[] double2int(double a[]) { int d[] = new int[a.length]; for (int k = 0; k < a.length; k++) { d[k] = (int) a[k]; if (d[k] < 0) d[k] = 0; if (d[k] > 255) d[k] = 255; } return d; } } class ImageCanvas extends Canvas { private Image image = null; private int rank = 0; public ImageCanvas(Image i) { setImage(i); } public void setImage(Image i) { image = i; setSize(i.getWidth(this), i.getHeight(this)); } public void setRank(int i) { rank = i; } public void paint(Graphics g) { if (image == null) return; g.drawImage(image, 0, 0, this); g.drawString(Integer.toString(rank), 10, 10); } }