/* * BugEyes.java * Distort an image * Usage: * * * Ken Shirriff ken.shirriff@eng.sun.com * * Copyright (c) 1996 Sun Microsystems, Inc. All Rights Reserved. * * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF * THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED * TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. * * Please refer to the file "license.txt" * for further important copyright and licensing information. */ import java.awt.*; import java.awt.image.*; import java.applet.Applet; public class BugEyes extends Applet implements Runnable, ImageObserver { int width, height; Image origimg=null, dispimg=null; Graphics gr; Thread warpthread = null; int pix[] = null; boolean down=false; boolean gotdata=false; boolean runningok=false; String status="Loading image"; Warp warp=new Warp2(); MediaTracker tracker; int mx0=0,my0=0,mx1=0,my1=0; static double param = 1; Scrollbar scroll = null; Button reset = null; Canvas can = null; int topmarg=0; int leftmarg=0; public void start() { warpthread=null; repaint(); } public void stop() { if (warpthread!=null) { warpthread.stop(); warpthread = null; } repaint(); } public boolean imageUpdate(Image origimg, int infoflags, int x, int y, int w, int h) { repaint(); return true; } public void init() { int i; String image = null; tracker = new MediaTracker(this); if (getParameter("image") != null) { image = getParameter("image"); } else { showStatus("BugEyes: no image specified"); return; } showStatus(status); origimg = getImage(getDocumentBase(),image); if (origimg==null) { status = "BugEyes: failed to load image"; showStatus(status); return; } tracker.addImage(origimg,0); try { tracker.waitForAll(); } catch (InterruptedException e) { } if (tracker.isErrorAny()) { status = "BugEyes: Error loading image"; showStatus(status); return; } width = origimg.getWidth(this); height = origimg.getHeight(this); can = new WarpCanvas(); can.resize(width, height); GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints gc = new GridBagConstraints(); setLayout(gridbag); gc.anchor = GridBagConstraints.NORTH; gc.gridwidth = GridBagConstraints.REMAINDER; gridbag.setConstraints(can,gc); add(can); scroll = new Scrollbar(Scrollbar.HORIZONTAL,0,20,0,100); scroll.setValue(100); gc.gridwidth = 1; Label sh = new Label("Shrink"); gridbag.setConstraints(sh,gc); add(sh); gc.fill = GridBagConstraints.HORIZONTAL; gc.weightx=1; gridbag.setConstraints(scroll,gc); add(scroll); gc.gridwidth = GridBagConstraints.REMAINDER; gc.weightx=0; gc.fill = GridBagConstraints.NONE; Label ex = new Label("Expand"); gridbag.setConstraints(ex,gc); add(ex); reset = new Button("Reset"); gc.gridwidth = GridBagConstraints.REMAINDER; gridbag.setConstraints(reset,gc); add(reset); Panel buf = new Panel(); gc.fill = GridBagConstraints.BOTH; gridbag.setConstraints(buf,gc); add(buf); super.layout(); topmarg = can.bounds().y; leftmarg = can.bounds().x; runningok=true; status = "BugEyes by Ken Shirriff"; showStatus(status); } public boolean handleEvent(Event e) { if (e.target.equals(scroll)) { param = scroll.getValue()/100.*2-1; } return super.handleEvent(e); } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { if (!runningok) { return; } if (pix==null) { // Create the pixel array the first time and fill // it with the image's pixels. pix = new int[width*height]; PixelGrabber grabber = new PixelGrabber(origimg, 0,0,width,height,pix,0,width); try { boolean s = false; while (s==false) { s = grabber.grabPixels(); } } catch (InterruptedException e) { } gotdata = true; dispimg = createImage(new MemoryImageSource(width, height, pix, 0, width)); } can.getGraphics().drawImage(dispimg,0,0,width,height,this); if (down) { warp.rubberBand(can.getGraphics(),mx0,my0,mx1,my1); } } public void run() { Image newimg; if (gotdata) { warp.warp(dispimg, width, height, mx0,my0,mx1,my1,pix); newimg = createImage(new MemoryImageSource(width, height, pix, 0, width)); tracker.addImage(newimg,0); try { tracker.waitForAll(); } catch (InterruptedException e) { } dispimg = newimg; } repaint(); status = "BugEyes by Ken Shirriff"; showStatus(""); warpthread = null; } public boolean mouseEnter(java.awt.Event evt, int xm, int ym) { showStatus(status); return true; } public boolean mouseExit(java.awt.Event evt, int xm, int ym) { showStatus(""); return true; } public boolean mouseDown(java.awt.Event evt, int xm, int ym) { showStatus("Select the region"); if (warpthread == null) { down = true; mx0 = xm-leftmarg; my0 = ym-topmarg; mx1 = xm-leftmarg; my1 = ym-topmarg; repaint(); } return true; } public boolean mouseDrag(java.awt.Event evt, int xm, int ym) { showStatus("Selecting region"); mx1 = xm-leftmarg; my1 = ym-topmarg; repaint(); return true; } public boolean mouseUp(java.awt.Event evt, int xm, int ym) { showStatus("Selected"); down = false; mx1 = xm-leftmarg; my1 = ym-topmarg; repaint(); if (warpthread==null) { status = "Warping image"; showStatus(status); warpthread = new Thread(this); warpthread.start(); } return true; } public boolean action(Event e, Object o) { if (e.target.equals(reset)) { pix = null; repaint(); } return true; } public String getAppletInfo() { return "Distort by Ken Shirriff shirriff@eng.sun.com"; } public String[][] getParameterInfo() { String [][] info = { {"width ","int ", "image width"}, {"height ","int ", "image height"}, {"image ","String ", "image url"} }; return info; } } abstract class Warp { public void rubberBand(Graphics g, int x0, int y0, int x1, int y1) { g.drawLine(x0,y0,x1,y1); } abstract void warp(Image origimg, int width, int height, int x0, int y0, int x1, int y1, int pix[]); public void circ(Graphics g, int x0, int y0, int x1, int y1) { int r = (int)Math.sqrt((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0)); g.drawOval(x0-r,y0-r,2*r,2*r); } public void grab(Image origimg,int x0,int y0,int w,int h,int width, int height,int inpxls[], int outpxls[]) { int off = 0; int realw=w, realh=h, realx0=x0, realy0=y0; if (x0<0) { realx0 = 0; } if (y0<0) { realy0 = 0; } for (int x=realx0;x=width) { break; } for (int y=realy0;y=height) { break; } outpxls[x-x0+(y-y0)*w]=inpxls[x+y*width]; } } } } // Warp the image. Note that different warp classes can be plugged in. class Warp2 extends Warp { public void rubberBand(Graphics g, int x0, int y0, int x1, int y1) { circ(g,x0,y0,x1,y1); } public void warp(Image origimg, int width, int height, int x0, int y0, int x1, int y1, int pix[]) { int r2 = (x1-x0)*(x1-x0)+(y1-y0)*(y1-y0); int r = (int)Math.sqrt((x1-x0)*(x1-x0)+(y1-y0)*(y1-y0)); if (r==0) { return; } int pixbak[] = new int[(2*r+1)*(2*r+1)]; grab(origimg,x0-r,y0-r,2*r+1,2*r+1,width,height,pix,pixbak); for (int yd=-r;yd<=r;yd++) { int y = y0+yd; if (y>=0 && y=0 && x2*r) { xa = 2*r; } if (ya>2*r) { ya = 2*r; } if (xa<0) { xa = 0; } if (ya<0) { ya = 0; } pix[x+y*width]=pixbak[xa+ya*(2*r+1)]; } } } } } } class WarpCanvas extends Canvas { public void update(Graphics g) { paint(g); } public void paint(Graphics g) { } }