/*
* 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) {
}
}