import java.applet.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; public class Twitch extends Applet implements Runnable { myCanvas cvs; Applet thisApplet; int numImgs = 2; Thread animator_thread = null; boolean please_stop = true; int delay = 0; int newExtent = 16, extent=16; double stretch = 0.7; int maxX = 320, maxY= 240; // image dimensions MediaTracker mt; Image img, mask, misImg; MemoryImageSource mis; boolean maskArray2d[][]; int maskArray1d[], misArray1d[], originalArray1d[], originalArray2d[][]; // to talk to pg int xc,yc, pxc, pyc; // center of locus of the distortion (&previous) int dir; // current direction of travel of the distortion locus center double angle; // cur distortion direction within locus public final static int N=0; public final static int NE=1; public final static int E=2; public final static int SE=3; public final static int S=4; public final static int SW=5; public final static int W=6; public final static int NW=7; /******************** begin class myCanvas*******************/ class myCanvas extends Canvas { Image img; public myCanvas(int w, int h) { super(); setSize(w,h); img = null; } public void update(Graphics g) { paint(g); } public void paint() { paint(getGraphics()); } public void paint(Graphics g) { if ((g!=null)&&(img!=null)) g.drawImage(img, 0,0, this); } } /******************** end class myCanvas*******************/ public void init() { thisApplet = this; loadImages(); arrayize(); gui(); listeners(); wigInit(); } void loadImages() { mt = new MediaTracker(this); img = getImage(getDocumentBase(), "imgs/geranium-pix.jpeg"); mt.addImage(img, 0); mask = getImage(getDocumentBase(), "imgs/geranium-mask.jpeg"); mt.addImage(mask, 1); } void arrayize() { PixelGrabber pg, mpg; int i,j,k; originalArray1d = new int[maxX*maxY]; originalArray2d = new int[maxX][maxY]; misArray1d = new int[maxX*maxY]; maskArray1d = new int[maxX*maxY]; maskArray2d = new boolean[maxX][maxY]; for(i=1; i<=numImgs; i++) { this.showStatus("Loading image "+i+" of "+numImgs+"..."); try{ mt.waitForID(i-1);} catch (InterruptedException e) { ; } if (mt.isErrorID(i-1)) { this.showStatus("mt barfed on image "+i+"; quitting."); return; } } this.showStatus("Images loaded."); pg = new PixelGrabber (img, 0, 0, maxX, maxY, originalArray1d, 0, maxX); try{ pg.grabPixels(); } catch (InterruptedException ie) { ; } mpg = new PixelGrabber (mask, 0, 0, maxX, maxY, maskArray1d, 0, maxX); try{ mpg.grabPixels(); } catch (InterruptedException ie) { ; } k=0; for (j=0; j60); k++; } } void gui() { thisApplet.setLayout(null); cvs = new myCanvas(maxX, maxY); cvs.setBounds(0,0, maxX, maxY); thisApplet.add(cvs); validate(); } void listeners() { cvs.addMouseListener (new MouseAdapter() { public void mouseEntered(MouseEvent e) { cvs.requestFocus(); } } ); cvs.addKeyListener (new KeyAdapter() { public void keyPressed(KeyEvent e) { // if we fix the mis to do the whole image with the // whole array always, maybe it never needs to stop. if (e.getKeyCode() == KeyEvent.VK_DOWN) { if (delay>0) delay*=2; else delay=1; } else if (e.getKeyCode() == KeyEvent.VK_UP) { delay/=2; } else if (e.getKeyCode() == KeyEvent.VK_LEFT) { if (extent>=4) { newExtent=extent/2; } } else if (e.getKeyCode() == KeyEvent.VK_RIGHT) { if (extent<64) { newExtent=extent*2; } } // else if (e.getKeyChar()=='0') {;} else if (Character.isDigit(e.getKeyChar())) { stretch = 0.1 * (double)Character.digit(e.getKeyChar(),10); } } } ); } void wigInit() { xc = (int)(Math.random() * ( maxX - 2*extent)) +extent; yc = (int)(Math.random() * ( maxY - 2*extent)) +extent; pxc=xc; pyc=yc; dir = (int)(Math.random() * 8.0); angle = 0.0; } // public void paint(Graphics g) { cvs.paint(); } // public void update(Graphics g) { paint(g); } public void run() { while (mis== null) {;} for (int i=0; i0) { try { Thread.sleep(delay); } catch (InterruptedException ie) { ; } } } for (int i=0; i=0)&&(yc-newExtent>=0) &&(xc+newExtent<320)&&(yc+newExtent<240)) extent = newExtent; else newExtent=extent; //Calc new patch x = stretch * Math.cos(angle); y = stretch * Math.sin(angle); for(j=0; j < (int)((double)extent*(1.0+y)); j++) for(i=0; i < (int)((double)extent*(1.0+x)); i++) misArray1d[(i+xc-extent) + (j+yc-extent)*maxX] = !maskArray2d[i+xc-extent][j+yc-extent]? originalArray2d[i+xc-extent][j+yc-extent]: originalArray2d [(int)((double)i/(1.0+x))+(xc-extent)] [(int)((double)j/(1.0+y))+(yc-extent)]; for(j=0; j < (int)((double)extent*(1.0+y)); j++) for(i=(int)((double)extent*(1.0+x)); i < 2*extent; i++) misArray1d[(i+xc-extent) + (j+yc-extent)*maxX] = !maskArray2d[i+xc-extent][j+yc-extent]? originalArray2d[i+xc-extent][j+yc-extent]: originalArray2d [(int)(((double)i-2.0*x*(double)extent)/(1.0-x))+(xc-extent)] [(int)((double)j/(1.0+y))+(yc-extent)]; for(j = (int)((double)extent*(1.0+y)); j<2*extent; j++) for(i=0; i < (int)((double)extent*(1.0+x)); i++) misArray1d[(i+xc-extent) + (j+yc-extent)*maxX] = !maskArray2d[i+xc-extent][j+yc-extent]? originalArray2d[i+xc-extent][j+yc-extent]: originalArray2d [(int)((double)i/(1.0+x))+(xc-extent)] [(int)(((double)j-2.0*y*(double)extent)/(1.0-y))+(yc-extent)]; for(j = (int)((double)extent*(1.0+y)); j<2*extent; j++) for(i = (int)((double)extent*(1.0+x)); i<2*extent; i++) misArray1d[(i+xc-extent) + (j+yc-extent)*maxX] = !maskArray2d[i+xc-extent][j+yc-extent]? originalArray2d[i+xc-extent][j+yc-extent]: originalArray2d [(int)(((double)i-2.0*x*(double)extent)/(1.0-x))+(xc-extent)] [(int)(((double)j-2.0*y*(double)extent)/(1.0-y))+(yc-extent)]; } void movePatch() { double coin; //update dir coin = Math.random(); // 0 to 1? if (coin <0.05) // then rot ccw { if (dir==0) dir=7; else dir--; } else if (coin>0.95) // then rot cw { if (dir==7) dir=0; else dir++; } //update angle angle += 0.1; //update xc,yc, pxc,pyc. pxc=xc; pyc=yc; switch(dir) { case N: if (ycmaxX-extent-1)&(ycmaxX-extent-1) //xc = extent; dir=NW; else xc++; if (ycmaxX-extent-1) //xc = extent; dir=W; else xc++; break; case SE: if ((xc>maxX-extent-1)&&(yc>maxY-extent-1)) dir=NW; else { if (xc>maxX-extent-1) //xc = extent; dir=SW; else xc++; if (yc>maxY-extent-1) //yc = extent; dir=NE; else yc++; } break; case S: if (yc>maxY-extent-1) //yc = extent; dir=N; else yc++; break; case SW: if ((xcmaxY-extent-1)) dir=NE; else { if (xcmaxY-extent-1) //yc = extent; dir=NW; else yc++; } break; case W: if (xc