home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Java 1.2 How-To
/
JavaHowTo.iso
/
code
/
ch07.txt
< prev
next >
Wrap
Text File
|
1998-12-14
|
43KB
|
2,170 lines
ImageApp.java:
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
/*
* display a series of images
*/
public class ImageApp extends Applet implements ActionListener
{
/*
* the number of images to load
*/
final int NumImages = 6;
Button button1;
/*
* an array to hold the images
*/
Image imgs[] = new Image[NumImages];
/*
* which image is currently displayed
*/
int which = 0;
/*
* init method runs when applet is loaded or reloaded
*/
public void init() {
setLayout(new BorderLayout());
Panel p = new Panel ();
add("South", p);
button1 = new Button("Next Image");
p.add (button1);
button1.addActionListener(this);
for (int i=0; i < NumImages; i+=1) {
String name = "Globe"+(i+1)+".gif";
imgs[i] = getImage (getDocumentBase(),name);
}
}
/**
* paint method is called by update
* draw the current image
* @param g - destination graphics object
*/
public void paint (Graphics g) {
g.drawImage (imgs[which], 10, 10, this);
}
/**
* switch to next image when button is pressed
* @param evt - event object
* @param arg - target object
*/
public void actionPerformed(ActionEvent evt)
{
which += 1;
which %= NumImages; // wrap around to zero
repaint (); // causes update as soon as possible
}
}
ImageSize.java:
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
/*
* an applet that allows an image to be resized
*/
public class ImageSize extends Applet implements ActionListener {
/*
* the image to draw
*/
Image img;
Button btnSmaller;
Button btnBigger;
/*
* the current width and height of the image
*/
double width, height;
/*
* the image size scale factor
*/
double scale = 1.0;
/*
* called when the applet is loaded or reloaded
*/
public void init() {
setLayout(new BorderLayout());
Panel p = new Panel ();
add("South", p);
btnSmaller = new Button("Smaller");
p.add (btnSmaller);
btnBigger = new Button("Bigger");
p.add (btnBigger);
btnSmaller.addActionListener(this);
btnBigger.addActionListener(this);
MediaTracker tracker = new MediaTracker (this);
img = getImage (getDocumentBase(), "T1.gif");
tracker.addImage (img, 0);
showStatus ("Getting image: T1.gif");
try {
tracker.waitForID (0);
} catch (InterruptedException e) { }
width = img.getWidth (this);
height = img.getHeight (this);
}
public void paint (Graphics g) {
double w, h;
w = scale * width;
h = scale * height;
// if we don't have the size yet, we shouldn't draw
if (w < 0 || h < 0) { w=75; h=75; } //return;
// explicitly specify width (w) and height (h)
g.drawImage (img, 10, 10, (int) w, (int) h, this);
}
public void actionPerformed(ActionEvent evt)
{
Object object1 = evt.getSource();
if (object1 == btnSmaller)
{
scale *= 0.9; // make it 10% smaller
repaint ();
}
if (object1 == btnBigger)
{
scale *= 1.1; // make it 10% bigger
repaint ();
}
}
}
ImageMove.java:
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
/*
* the applet class
*/
public class ImageMove extends Applet implementsσ
MouseListener, MouseMotionListener{
/*
* the image to be displayed
*/
Image img;
/*
* the width and height of the image
*/
int width, height;
/*
* xpos, ypos are the coordinates of the upper left of the image
*/
int xpos=10, ypos=10;
/*
* dx, dy are the deltas from the mouse point to xpos, ypos
*/
int dx, dy;
/*
* called when the applet is loaded
* load the image and use MediaTracker so that
* the width and height are available immediately
*/
public void init () {
MediaTracker tracker = new MediaTracker (this);
img = getImage (getDocumentBase(), "T1.gif");
tracker.addImage (img, 0);
showStatus ("Getting image: T1.gif");
try {
tracker.waitForID (0);
} catch (InterruptedException e) { }
width = img.getWidth (this);
height = img.getHeight (this);
addMouseListener(this);
addMouseMotionListener(this);
}
/*
* paint the image in the new location
* @param g - destination graphics object
*/
public void paint (Graphics g) {
g.setColor (Color.white);
g.drawImage (img, xpos, ypos, this);
}
/*
* adjust the new position and repaint the image
*/
public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseReleased(MouseEvent e){}
public void mouseMoved(MouseEvent e){}
public void mousePressed(MouseEvent e)
{
int x =e.getX();
int y =e.getY();
dx = x - xpos;
dy = y - ypos;
}
public void mouseDragged(MouseEvent e)
{
int x =e.getX();
int y =e.getY();
if (dx < width && dx >= 0 && dy < height && dy >= 0)
{
xpos = x - dx;
ypos = y - dy;
repaint ();
}
}
}
Bounce.java:
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import java.awt.image.ImageObserver;
/*
* a class describing a single ball
*/
class Ball {
/*
* the image for this ball
*/
Image img;
/*
* x position and velocity
*/
double x, dx;
/*
* y position and velocity
*/
double y, dy;
/*
* initialize the position and velocity
* to random values
*/
void random () {
x = 10 + 380*Math.random ();
y = 10 + 200*Math.random ();
dx = 5 - 10*Math.random ();
dy = 5 - 10*Math.random ();
}
/**
* calculate the next position of this ball
* and make sure it bounces off the edge of the panel
* @param d - dimension of the bounding panel
*/
void compute (Dimension d) {
if (x <= 0 || x > d.width) dx = -dx; // bounce horizontal
if (y <= 0 || y > d.height) dy = -dy; // bounce vertical
x += dx;
y += dy;
}
/**
* draw the ball image
* @param g - destination graphics object
* @param obs - parent image observer
*/
public void paint (Graphics g, ImageObserver obs) {
g.drawImage (img, (int) x-10, (int) y-10, obs);
}
}
/*
* the panel containing the bouncing balls
*/
class BouncePanel extends Panel implements Runnable {
/*
* the number of balls
*/
final int nballs = 4;
/*
* the array holding all the balls
*/
Ball balls[] = new Ball[10];
/*
* offscreen image
*/
Image offimg;
/*
* size of offscreen image
*/
Dimension offsize;
/*
* graphics object associated with offscreen image
*/
Graphics offg;
/*
* thread for periodic updating
*/
Thread thread;
/*
* the thread recalculates each ball position and
* redraws them
*/
public void run() {
offsize = getSize();
offimg = createImage (offsize.width, offsize.height);
offg = offimg.getGraphics();
while (true) {
for (int i=0; i<nballs; i+=1) {
balls[i].compute (offsize);
}
repaint ();
try {
Thread.sleep (25);
} catch (InterruptedException e) {
break;
}
}
}
/**
* override update to avoid erase flicker
* @param g - destination graphics object
*/
public synchronized void update (Graphics g) {
offg.setColor (Color.lightGray);
offg.fillRect (0, 0, offsize.width, offsize.height);
for (int i = 0 ; i < nballs ; i++)
balls[i].paint (offg, this);
offg.setColor (Color.black);
offg.drawRect (0, 0, offsize.width-1, offsize.height-1);
g.drawImage(offimg, 0, 0, this);
}
/*
* start the update thread
*/
public void start() {
thread = new Thread(this);
thread.start();
}
/*
* stop the update thread
*/
public void stop() {
if (thread != null)
{
thread = null;
}
}
}
/*
* the applet proper
*/
public class Bounce extends Applet implements ActionListener {
/*
* instance of BouncePanel
*/
BouncePanel panel;
Button button1;
/*
* an array containing the images for the balls
*/
Image img[] = new Image[4];
/*
* called when the applet is loaded
* create an instance of bounce panel and add the Start button
* and load images
*/
public void init() {
setLayout(new BorderLayout());
panel = new BouncePanel ();
add ("Center", panel);
Panel p = new Panel ();
add ("South", p);
button1 = new Button("Start");
p.add (button1);
button1.addActionListener(this);
img[0] = getImage (getDocumentBase(), "whiteball.gif");
img[1] = getImage (getDocumentBase(), "redball.gif");
img[2] = getImage (getDocumentBase(), "blueball.gif");
img[3] = getImage (getDocumentBase(), "greenball.gif");
for (int i=0; i<panel.nballs; i+=1) {
panel.balls[i] = new Ball ();
panel.balls[i].img = img[i & 3];
}
}
/*
* called when the applet is started
* just start the bounce panel update thread
*/
public void start() {
panel.start();
}
/*
* called when the applet is stopped
*/
public void stop() {
panel.stop();
}
/*
* handle Start button press by randomizing balls
* @param evt - event object
* @param arg - target object
*/
public void actionPerformed(ActionEvent evt)
{
for (int i=0; i<panel.nballs; i+=1)
panel.balls[i].random ();
}
}
LayerApp.java:
import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;
import java.awt.image.*;
/*
* class for handling one image
*/
class Picture {
/*
* position of the image
*/
int xpos, ypos;
/*
* width and height of the image
*/
int width, height;
/*
* the image itself
*/
Image image;
ImageObserver obs;
/**
* constructor saves arguments
* @param img - the image
* @param x, y - initial position
* @param o - imageObserver of parent
*/
public Picture (Image img, int x, int y, ImageObserver o) {
image = img;
xpos = x;
ypos = y;
obs = o;
width = image.getWidth (obs);
height = image.getHeight (obs);
}
/**
* determine whether the point is inside this image
* @param x, y - coordinate of point
*/
boolean inside (int x, int y) {
if (x < xpos || x > (xpos+width)) return false;
if (y < ypos || y > (ypos+height)) return false;
return true;
}
/**
* set the current position of the image
* @param x, y - position to set
*/
void setPosition (int x, int y) {
xpos = x;
ypos = y;
}
/**
* draw the image
* draw a green border around the image if
* highlight is true
* @param g - destination graphics object
* @param highlight - draw border
*/
void paint (Graphics g, boolean highlight) {
if (highlight) {
g.setColor (Color.green);
g.fillRect (xpos-5, ypos-5, width+10, height+10);
}
g.drawImage (image, xpos, ypos, obs);
}
}
/*
* the applet
*/
public class LayerApp extends Applet implements MouseListener,
MouseMotionListener, ActionListener
{
/*
* the number of picture objects
*/
final int NPictures = 4;
/*
* an array containing the picture objects
*/
Picture pictures[] = new Picture[NPictures];
/*
* the user-selected picture
*/
int selectedPic = -1;
/*
* offsets from mouse to image origin
*/
int dx, dy;
/*
* offscreen image for double-buffering
*/
Image offimg;
Button btnBring;
Button btnSend;
/*
* offscreen graphics context associated with
* offscreen image
*/
Graphics offg;
/*
* dimension of offscreen image
*/
Dimension offsize;
/*
* called when the applet is loaded
*/
public void init() {
setLayout(new BorderLayout());
Panel p = new Panel ();
add ("South", p);
btnBring = new Button("Bring to front");
btnSend = new Button("Send to back");
p.add(btnBring);
p.add(btnSend);
addMouseListener(this);
addMouseMotionListener(this);
btnBring.addActionListener(this);
btnSend.addActionListener(this);
int i;
Image img;
String name;
MediaTracker tracker = new MediaTracker (this);
offsize = getSize();
offimg = createImage (offsize.width, offsize.height);
offg = offimg.getGraphics();
for (i=0; i<NPictures; i+=1) {
if (i < 2) name = "T"+(i+1)+".jpg";
else name = "T"+(i+1)+".gif";
img = getImage (getDocumentBase(), name);
tracker.addImage (img, i);
showStatus ("Getting image: "+name);
try {
tracker.waitForID (i);
} catch (InterruptedException e) { }
pictures[i] = new Picture (img, i*10, i*20, this);
}
}
/**
* reverse the order of update for efficiency
* @param g - destination graphics object
*/
public void paint (Graphics g) {
update (g);
}
/**
* override update to avoid erase flicker
* @param g - destination graphics object
*/
public void update (Graphics g) {
int i;
offg.setColor (Color.black);
offg.fillRect (0, 0, offsize.width, offsize.height);
for (i=0; i<NPictures; i+=1) {
if (i == selectedPic) pictures[i].paint (offg, true);
else pictures[i].paint (offg, false);
}
g.drawImage(offimg, 0, 0, this);
}
/**
* determine which image the user clicked
* @param evt - event object
* @param x, y - mouse position
*/
public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseReleased(MouseEvent e)
{
repaint ();
}
public void mouseMoved(MouseEvent e){}
public void mousePressed(MouseEvent e)
{
int x =e.getX();
int y =e.getY();
int i;
selectedPic = -1;
for (i=NPictures-1; i>=0; i-=1)
{
if (pictures[i].inside (x, y))
{
selectedPic = i;
dx = x - pictures[i].xpos;
dy = y - pictures[i].ypos;
break;
}
}
}
public void mouseDragged(MouseEvent e)
{
int x =e.getX();
int y =e.getY();
int i;
if (selectedPic < 0) return;
/* for (i=NPictures-1; i>=0; i-=1)
{
pictures[selectedPic].setPosition (x - dx, y - dy);
repaint ();
} */
}
/**
* reorder the images depending on which button is pressed
* @param evt - event object
* @param arg - target object
*/
public void actionPerformed(ActionEvent evt)
{
Object object1 = evt.getSource();
int i;
Picture temp;
if (object1 == btnBring) {
if (selectedPic < 0) return;
temp = pictures[selectedPic];
for (i=selectedPic; i<NPictures-1; i+=1)
{
pictures[i] = pictures[i+1];
}
pictures[NPictures-1] = temp;
selectedPic = NPictures - 1;
repaint ();
return;
}
if (object1 == btnSend)
{
if (selectedPic < 0) return;
temp = pictures[selectedPic];
for (i=selectedPic; i>0; i-=1)
{
pictures[i] = pictures[i-1];
}
pictures[0] = temp;
selectedPic = 0;
repaint ();
return;
}
}
}
Advertiser.java:
import java.util.*;
import java.awt.*;
import java.applet.Applet;
/*
* A class that performs the banner animation
*/
class Banner extends Panel implements Runnable {
/*
* an instance of the applet for
* invoking methods from the Advertiser class
*/
Advertiser advertiser;
/*
* instance of thread used for animation
*/
Thread thread;
/*
* the next banner image to be displayed
*/
Image theImage;
/*
* width and height of the new banner image
*/
int img_width, img_height;
/*
* offscreen image for double-buffering
*/
Image offscreen;
/*
* offg1 is the graphics object associated with
* offscreen image. offg2 is the clipped version
* of offg1
*/
Graphics offg1, offg2;
/*
* xstart, ystart - x and y coordinate of clipping rectangle
* width, height - width and height of clipping rectangle
* effect_type - the effect type applied to the next image
*/
int xstart, ystart, width, height, effect_type;
/**
* constructor just saves instance of the applet
* @param advertiser - instance of advertiser applet
*/
Banner (Advertiser advertiser) {
this.advertiser = advertiser;
}
/*
* thread that calls repaint() every 25ms
* to effect animation
*/
public void run() {
Dimension d = getSize();
offscreen = createImage (d.width, d.height);
offg1 = offscreen.getGraphics ();
offg1.setFont (getFont ());
offg1.setColor (Color.gray);
offg1.fillRect (0, 0, d.width, d.height);
while (true) {
repaint ();
try {
Thread.sleep (25);
} catch (InterruptedException e) {
break;
}
}
}
/**
* override update() method to avoid erase flicker
* this is where the drawing is done
* @param g - destination graphics object
*/
public synchronized void update(Graphics g) {
int i, x, y, w, h;
switch (effect_type) {
case 0:
offg1.drawImage (theImage, 0, 0, null);
break;
case 1: // barn-door open
if (xstart > 0) {
xstart -= 5;
width += 10;
offg2 = offg1.create (xstart, 0, width, height);
offg2.drawImage (theImage, -xstart, 0, null);
} else offg1.drawImage (theImage, 0, 0, null);
break;
case 2: // venetian blind
if (height < 10) {
height += 1;
for (y=0; y<img_height; y+=10) {
offg2 = offg1.create (0, y, width, height);
offg2.drawImage (theImage, 0, -y, null);
}
} else offg1.drawImage (theImage, 0, 0, null);
break;
case 3: // checkerboard
if (width <= 20) {
if (width <= 10) {
i = 0;
for (y=0; y<img_height; y+=10) {
for (x=(i&1)*10; x<img_width; x+=20) {
offg2 = offg1.create (x, y, width, 10);
offg2.drawImage (theImage, -x, -y,σ
null);
}
i += 1;
}
} else {
i = 1;
for (y=0; y<img_height; y+=10) {
for (x=(i&1)*10; x<img_width; x+=20) {
offg2 = offg1.create (x, y,[cc]
width-10, 10);
offg2.drawImage (theImage,σ
-x, -y, null);
}
i += 1;
}
}
width += 5;
} else offg1.drawImage (theImage, 0, 0, null);
break;
}
g.drawImage (offscreen, 0, 0, null);
}
/**
* initialize variables for clipping rectangle
* depending on effect type
* @param which - the effect type for next image
* @param img - the next image
*/
public void effect (int which, Image img) {
img_width = img.getWidth (null);
img_height = img.getHeight (null);
theImage = img;
switch (which) {
case 0:
break;
case 1: // barn door
xstart = img_width >> 1;
width = 0;
height = img_height;
break;
case 2:
width = img_width;
height = 0;
break;
case 3:
width = 0;
break;
}
effect_type = which;
}
/*
* start the repaint thread
*/
public void start() {
thread = new Thread(this);
thread.start();
}
/*
* stop the repaint thread
*/
public void stop() {
if (thread != null)
thread = null;
}
}
/*
* the Advertiser class proper
*/
public class Advertiser extends Applet implements Runnable {
/*
* instance of Banner
*/
Banner panel;
/*
* instance of thread for cycling effects
* for each new image
*/
Thread thread;
/*
* the total number of images
*/
int NBanners;
/*
* the array of images
*/
Image img[] = new Image[10];
/*
* the delay (dwell) time in milliseconds for each image
*/
int delay[] = new int[10];
/*
* the effect type for each image
*/
int effect[] = new int[10];
/*
* called when applet is loaded
* add the banner panel, load images, and parse applet
* parameters
*/
public void init() {
int i;
setLayout(new BorderLayout());
panel = new Banner (this);
add("Center", panel);
NBanners = 0;
MediaTracker tracker = new MediaTracker (this);
for (i=1; i<=10; i+=1) {
String param, token;
int j, next;
param = getParameter ("T"+i);
if (param == null) break;
StringTokenizer st = new StringTokenizer (param, " ,");
token = st.nextToken ();
img[NBanners] = getImage (getDocumentBase(), token);
tracker.addImage (img[NBanners], i);
showStatus ("Getting image: "+token);
try {
tracker.waitForID (i);
} catch (InterruptedException e) { }
token = st.nextToken ();
delay[NBanners] = Integer.parseInt (token);
token = st.nextToken ();
effect[NBanners] = Integer.parseInt (token);
NBanners += 1;
}
}
/*
* thread that starts the next image transition
*/
public void run () {
int current = 0;
while (true) {
panel.effect (effect[current], img[current]);
try {
Thread.sleep (delay[current]);
} catch (InterruptedException e) { }
current += 1;
current %= NBanners;
}
}
/*
* called when applet is started
* start both threads
*/
public void start() {
panel.start();
thread = new Thread(this);
thread.start();
}
/*
* called when applet is stopped
* stops all threads
*/
public void stop() {
panel.stop();
if (panel != null)
panel = null;
if (thread != null)
thread = null;
}
}
Mandelbrot.java:
import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
/*
* a class for generating and displaying the
* Mandelbrot set
*/
public class Mandelbrot extends Applet implements MouseListener,
MouseMotionListener, ActionListener
{
/*
* the maximum number of colors for
* each pixel
*/
final int MaxColors = 256;
/*
* the width and height of the image
*/
int mWidth, mHeight;
/*
* the array of pixel values
*/
int pixels[];
/*
* the set values
*/
int mandelSet[];
/*
* the image produce by the set
*/
Image theImage = null;
/*
* the mapping function from set values to pixel values
*/
int pixMap[] = new int[MaxColors];
/*
* a flag used for recalculating
*/
boolean startCalculate = false;
/*
* instance of MandelRect class
*/
MandelRect mandelRect;
/*
* the control buttons
*/
Button startButton;
Button zoomButton;
/*
* called when the applet is loaded
* initialize the pixmap array and add user interface
*/
public void init () {
mWidth = 100;
mHeight = 100;
pixels = new int [mWidth * mHeight];
mandelSet = new int [mWidth * mHeight];
mandelRect = new MandelRect (mWidth, mHeight);
int red, green, blue;
int i;
pixMap[0] = 0xffffffff;
for (i=1; i<MaxColors-1; i+=1) {
red = i;
green = (i<128) ? i << 1 : 255-(i<<1);
blue = MaxColors-i;
pixMap[i] = (255 << 24) | (red << 16) | (green << 8) | blue;
}
pixMap[MaxColors-1] = 0xff000000;
setLayout(new BorderLayout());
startButton = new Button ("Start over");
zoomButton = new Button ("Zoom in");
startButton.addActionListener(this);
zoomButton.addActionListener(this);
addMouseListener(this);
addMouseMotionListener(this);
Panel p = new Panel ();
p.setLayout (new FlowLayout ());
p.add (startButton);
p.add (zoomButton);
add ("South", p);
}
/*
* called when the applet is started
* forces a recalculation of the set
*/
public void start () {
startCalculate = true;
repaint ();
}
/*
* call update for efficiency
* @param g - destination graphics object
*/
public void paint (Graphics g) {
update (g);
}
/**
* override default update() method to avoid erase flicker
* @param g - destination graphics object
*/
public void update (Graphics g) {
if (startCalculate) {
calculate ();
startCalculate = false;
}
if (theImage != null) g.drawImage (theImage, 0, 0, this);
else repaint (1000);
mandelRect.paint (g);
}
/*
* perform the actual set calculation
*/
void calculate () {
int i, index;
double width, height;
double row, col;
double zr, zi, cr, ci, tzr, tzi;
double hFactor, vFactor;
double x, y;
theImage = null;
x = mandelRect.mandelX;
y = mandelRect.mandelY;
width = (double) mandelRect.imgWidth;
height = (double) mandelRect.imgHeight;
hFactor = mandelRect.mandelWidth/width;
vFactor = mandelRect.mandelHeight/height;
index = 0;
for (row=0; row<height; row+=1) {
for (col=0; col<width; col+=1) {
zr = 0;
zi = 0;
cr = x + col * hFactor;
ci = y + row * vFactor;
for (i=1; i<64; i+=1) {
tzr = zr*zr - zi*zi + cr;
tzi = 2*zr*zi + ci;
zr = tzr;
zi = tzi;
if (zr*zr + zi*zi > 4.0) break;
}
mandelSet[index++] = (i << 2)-1;
}
}
for (i=0; i<mWidth*mHeight; i+=1) {
pixels[i] = pixMap[mandelSet[i]];
}
theImage = createImage (
new MemoryImageSource(mWidth, mHeight, pixels, 0, mWidth));
}
public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseReleased(MouseEvent e)
{
int x =e.getX();
int y =e.getY();
mandelRect.setWidthHeight (x, y);
mandelRect.setPaintRect (true);
repaint ();
}
public void mouseMoved(MouseEvent e){}
public void mousePressed(MouseEvent e)
{
int x =e.getX();
int y =e.getY();
mandelRect.setXY (x, y);
}
public void mouseDragged(MouseEvent e)
{
int x =e.getX();
int y =e.getY();
mandelRect.setWidthHeight (x, y);
mandelRect.setPaintRect (true);
repaint ();
}
/**
* reorder the images, depending on which button is pressed
* @param evt - event object
* @param arg - target object
*/
public void actionPerformed(ActionEvent evt)
{
Object object1 = evt.getSource();
if (object1 == startButton) {
mandelRect = new MandelRect (mWidth, mHeight);
startCalculate = true;
repaint ();
}
if (object1 == zoomButton)
{
startCalculate = true;
mandelRect.setPaintRect (false);
mandelRect.scaleSet ();
repaint ();
}
}
/**
* application entry point
* create window and new set
* @param args - command-line arguments
*/
public static void main (String args[]) {
Frame f = new Frame ("Mandelbrot set");
Mandelbrot mandel = new Mandelbrot ();
mandel.init ();
f.setSize (210, 275);
f.add ("Center", mandel);
f.show ();
f.addWindowListener(new WindowCloser());
mandel.start ();
}
}
class WindowCloser extends WindowAdapter
{
public void windowClosing(WindowEvent e)
{
Window win = e.getWindow();
win.setVisible(false);
win.dispose();
System.exit(0);
}
}
MandelRect.java:
import java.awt.*;
/*
* a helper class to manage the zoom rectangle
*/
public class MandelRect {
/*
* the coordinates of the zoom rectangle
* in screen space
*/
int x;
int y;
int width;
int height;
/*
* the final image width and height
*/
int imgWidth;
int imgHeight;
/*
* the coordinates of the zoom rectangle
* in set space
*/
double mandelX;
double mandelY;
double mandelWidth;
double mandelHeight;
/*
* set to true if the zoom rectangle should be painted
*/
boolean paintRect;
/**
* constructor initializes variables
* @param iW - final image width
* @param iH - final image height
*/
public MandelRect (int iW, int iH) {
imgWidth = iW;
imgHeight = iH;
paintRect = false;
mandelX = -1.75;
mandelY = -1.125;
mandelWidth = 2.25;
mandelHeight = 2.25;
}
/**
* set the top left of the zoom rectangle in screen space
* @param ix, iy - top-left corner of zoom rectangle
*/
void setXY (int ix, int iy) {
x = ix;
y = iy;
}
/**
* set the width, height of the zoom rectangle in screen space
* @param ix, iy - bottom-right corner of zoom rectangle
*/
void setWidthHeight (int ix, int iy) {
width = ix - x;
height = iy - y;
}
/*
* translate screen coordinates to set coordinates
*/
void scaleSet () {
int tx, ty, tw, th;
tx = x;
ty = y;
tw = width;
th = height;
if (tw < 0) {
tw = -width;
tx = x-tw;
}
if (th < 0) {
th = -height;
ty = y-th;
}
mandelX = mandelX + (mandelWidth) * ((double) tx)/((double) imgWidth);
mandelY = mandelY + (mandelHeight) * ((double) ty)/((double) imgHeight);
mandelWidth = mandelWidth * ((double) tw)/((double)imgWidth);
mandelHeight = mandelHeight * ((double) th)/((double)imgHeight);
}
/**
* set the paintRect flag
* @param p - true means zoom rectangle should be painted
*/
void setPaintRect (boolean p) {
paintRect = p;
}
/**
* paint the zoom rectangle if necessary
* @param g - destination graphics object
*/
void paint (Graphics g) {
if (paintRect == false) return;
int tx, ty, tw, th;
tx = x;
ty = y;
tw = width;
th = height;
if (tw < 0) {
tw = -width;
tx = x-tw;
}
if (th < 0) {
th = -height;
ty = y-th;
}
g.setColor (Color.white);
g.drawRect (tx, ty, tw, th);
}
}
LifeApp.java:
import java.util.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.ImageObserver;
import java.awt.image.PixelGrabber;
/*
* class that manages a generation
*/
class LifeGenerator {
/*
* array containing packed cells
* n - number of elements in the CellList array
*/
int CellList[], n;
int a[];
int b[];
int c[];
/*
* the current generation number
*/
int generations;
/*
* background and foreground colors
*/
Color background;
Color foreground;
int statusheight;
int displaywidth;
int displayheight;
int originx;
int originy;
int maxcells;
static int countmsk=0x1f;
static int posmsk=0x7fffffe0;
static int maxval=0x7fffffff;
String statusLine;
String loading;
int scroll;
/*
* the rules of life
*/
static boolean rules[]={
false, false,
false, false,
false, true,
true, true,
false, false,
false, false,
false, false,
false, false,
false, false
};
/*
* constructor initializes variables
*/
public LifeGenerator() {
n=0;
generations=0;
maxcells=0;
background=Color.white;
foreground=Color.black;
originx=0;
originy=0;
loading=null;
scroll=10;
statusLine=new String("");
}
public void loading(String init_loading) {
loading=init_loading;
}
public void setScroll(int init_scroll) {
scroll=init_scroll;
}
public void setColors(Color init_background,Color init_foreground) {
background=init_background;
foreground=init_foreground;
}
public void setDisplaySize(int width, int height) {
statusheight=35;
displaywidth=width;
displayheight=height-statusheight;
}
/**
* translate the origin
* @param dx, dy - offsets to translate
*/
public void translate(int dx, int dy) {
originx+=dx;
originy+=dy;
}
public void recenter(int x, int y) {
translate(displaywidth/2-x, displayheight/2-y);
}
public void approachcenter(int x, int y) {
translate((displaywidth/2-x)/scroll,
(displayheight/2-y)/scroll);
}
public void findPattern() {
if (n>0) {
int packed=CellList[n/2];
int plotx=(((packed>>5)&0x1fff)-(1<<12))*2+originx;
int ploty=((packed>>18)-(1<<12))*2+originy;
recenter(plotx, ploty);
}
}
/**
* print status message
* @param g - destination graphics object
*/
public void updateStatusLine(Graphics g) {
g.setColor(background);
g.drawString(statusLine,0,displayheight+15);
if (loading!=null) {
statusLine="Loading: " + loading;
} else {
statusLine="Generations: " + generations + " Cells: " + n;
}
g.setColor(foreground);
g.drawString(statusLine,0,displayheight+15);
}
void resizeIfNeeded(int cellcount) {
int tmp[];
int i;
if (cellcount>maxcells) {
int newsize=2*cellcount;
tmp=new int[newsize];
for (i=0; i<maxcells; i++) tmp[i]=CellList[i];
CellList=tmp;
tmp=new int[newsize];
for (i=0; i<maxcells; i++) tmp[i]=a[i];
a=tmp;
tmp=new int[newsize];
for (i=0; i<maxcells; i++) tmp[i]=b[i];
b=tmp;
tmp=new int[newsize];
for (i=0; i<maxcells; i++) tmp[i]=c[i];
c=tmp;
maxcells=newsize;
}
}
static int combineLists(int a[], int na, int b[], int nb,int c[]) {
int i,j,nc;
i=0; j=0; nc=0;
a[na]=maxval;
b[nb]=maxval;
while (i<na || j<nb) {
if ((a[i]^b[j])<=countmsk) {
c[nc++]=(a[i++]&countmsk)+b[j++];
} else if (a[i]<b[j]) {
c[nc++]=a[i++];
} else {
c[nc++]=b[j++];
}
}
return nc;
}
static void extractCenterCells(int list[], int n, int counts[]) {
int i=0, j=0;
while (i<n) {
if ((list[i]^counts[j])<=countmsk) {
counts[j]-;
i++;
j++;
} else j++;
}
}
static int Cell(int x, int y, int value) {
return ((y+(1<<12))<<18) +((x+(1<<12))<<5) + value;
}
/**
* plot an individual cell
* @param packed - a set of packed cells
* @param g - destination graphics object
*/
void plotCell(int packed, Graphics g) {
int plotx=(((packed>>5)&0x1fff)-(1<<12))*2+originx;
int ploty=((packed>>18)-(1<<12))*2+originy;
if (plotx > 3 && plotx < displaywidth-5 &&
ploty > 3 && ploty < displayheight-5 ) {
g.fillRect(plotx, ploty, 2, 2);
}
}
/**
* paint the current generation
* @param g - destination graphics object
*/
public void paintAll(Graphics g) {
g.clearRect(0,0,displaywidth, displayheight+statusheight);
g.drawRect(0,0,displaywidth-1, displayheight-1);
g.setColor(foreground);
for (int i=0; i<n; i++) {
plotCell(CellList[i],g);
}
updateStatusLine(g);
}
int nextGen(int counts[], int ncounts, int list[], Graphics g) {
int nlist=0;
for (int i=0; i<ncounts; i++) {
int count=counts[i]&countmsk;
if (rules[count]) {
list[nlist++]=(counts[i]&posmsk)+2;
if ((count&1)==0) {
g.setColor(foreground);
plotCell(counts[i],g);
}
} else {
if ((count&1)==1) {
g.setColor(background);
plotCell(counts[i],g);
}
}
}
return nlist;
}
public void generate(Graphics g) {
int na, nb, nc;
for (na=0; na<n; na++) a[na]=CellList[na]-(1<<18);
resizeIfNeeded(n+na);
nb=combineLists(CellList,n,a,na,b);
for (na=0; na<n; na++) a[na]=CellList[na]+(1<<18);
resizeIfNeeded(na+nb);
nc=combineLists(a,na,b,nb,c);
for (na=0; na<nc; na++) a[na]=c[na]-(1<<5);
resizeIfNeeded(na+nc);
nb=combineLists(a,na,c,nc,b);
for (na=0; na<nc; na++) a[na]=c[na]+(1<<5);
resizeIfNeeded(na+nb);
nc=combineLists(a,na,b,nb,c);
extractCenterCells(CellList, n, c);
n=nextGen(c, nc, CellList, g);
generations++;
}
/**
* load a new initial image
* @param img - the image to load
* @param imgobs - the image observer
*/
public boolean loadLifePattern(Image img, ImageObserver imgobs) {
int w=img.getWidth(imgobs);
int h=img.getHeight(imgobs);
if (w<0 || h<0) return false;
originx= (displaywidth-w*2)/2;
originy= (displayheight-h*2)/2;
int[] pixels = new int[w * h];
PixelGrabber pg = new PixelGrabber(img, 0, 0, w, h, pixels, 0, w);
try {
pg.grabPixels();
} catch (InterruptedException e) {
return false;
}
int i,j;
int pix0= pixels[0];
int pix1= -1;
int count1= 0;
for (i=0; i<h; i++) {
for (j=0; j<w; j++) {
if (pixels[i*w+j]!=pix0) {
pix1= pixels[i*w+j];
count1++;
}
}
}
/* figure out which pixel color denotes a live cell */
if (pix0==0xffffff) {}
else if (pix1==0xffffff || count1 > w*h-count1) {
pix1=pix0;
count1=w*h-count1;
}
resizeIfNeeded(count1);
n=0;
for (i=0; i<h; i++) {
for (j=0; j<w; j++) {
if (pixels[i*w+j]==pix1) {
CellList[n++]=Cell(j,i,2);
}
}
}
return true;
}
}
/*
* the applet class
*/
public class LifeApp extends java.applet.Applet implements MouseListener,
ActionListener, Runnable {
LifeGenerator LifeList;
/*
* the thread controlling generations
*/
Thread killme=null;
int speed=50;
boolean neverPainted=true;
int count=0;
/*
* the image name text field
*/
TextField patfield;
Button pausebutton;
Button stepbutton;
Button recenterbutton;
Button loadbutton;
boolean generating=false;
int stepsleft=0;
int scrollfraction=5;
/*
* called when applet is loaded
* create user interface and parse applet parameters
*/
public void init() {
setLayout(new FlowLayout(FlowLayout.RIGHT, 0, getSize().height-30));
add(pausebutton=new Button("Start"));
add(stepbutton = new Button("Step"));
add(recenterbutton = new Button("Recenter"));
add(loadbutton = new Button("Load:"));
pausebutton.addActionListener(this);
stepbutton.addActionListener(this);
recenterbutton.addActionListener(this);
loadbutton.addActionListener(this);
addMouseListener(this);
String patname=getParameter("pattern");
if (patname==null) patname="gun30";
if (getParameter("started")!=null) {
pausebutton.setLabel("Stop");
generating=true;
}
String pstring;
if ((pstring=getParameter("speed"))!=null) {
speed=Integer.valueOf(pstring).intValue();
}
if ((pstring=getParameter("scrollfraction"))!=null) {
scrollfraction=Integer.valueOf(pstring).intValue();
}
add(patfield=new TextField(patname,8));
LifeList=null;
}
/*
* called when applet is started
* start the life thread
*/
public void start() {
if (killme==null) {
killme=new Thread(this);
killme.start();
}
}
/*
* called when the applet is stopped
* stop the life thread
*/
public void stop() {
killme=null;
}
//********************************************************
public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
public void mouseReleased(MouseEvent e)
{
}
public void mousePressed(MouseEvent e)
{
int x =e.getX();
int y =e.getY();
LifeList.approachcenter(x,y);
LifeList.paintAll(getGraphics());
}
/**
* reorder the images, depending on which button is clicked
* @param evt - event object
* @param arg - target object
*/
public void actionPerformed(ActionEvent evt)
{
boolean acted=true;
boolean damage=true;
Object object1 = evt.getSource();
if (object1 == pausebutton)
{
String label= pausebutton.getLabel();
if (label == "Stop")
{
pausebutton.setLabel("Start");
generating=false;
} else if (label == "Start")
{
pausebutton.setLabel("Stop");
generating=true;
}
}
if (object1 == stepbutton)
{
stepsleft=1;
if (generating)
{
pausebutton.setLabel("Start");
generating=false;
}
}
if (object1 == recenterbutton)
{
LifeList.findPattern();
}
if (object1 == loadbutton)
{
stop();
LifeList=null;
start();
}
if (acted && damage) LifeList.paintAll(getGraphics());
}
//***********************************************************
/**
* add .gif to the filename
* @param patname - base filename
*/
static String makeGifName(String patname) {
int i=patname.indexOf(".");
String base=(i<0)?patname:patname.substring(0,i);
return base.concat(".gif");
}
/**
* load new image file
* @parame patname - name of image file
*/
void loadNew(String patname) {
Image img=getImage(getCodeBase(), makeGifName(patname));
LifeList.loading(patname);
LifeList.paintAll(getGraphics());
while(killme!=null && !LifeList.loadLifePattern(img,
σthis)) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {}
}
LifeList.loading(null);
LifeList.paintAll(getGraphics());
}
/*
* life thread
* causes new generations to be created
*/
public void run() {
Graphics g=getGraphics();
if (LifeList==null) {
LifeList = new LifeGenerator();
LifeList.setColors(getBackground(), Color.black);
LifeList.setScroll(scrollfraction);
LifeList.setDisplaySize(getSize().width, getSize().height);
loadNew(patfield.getText());
}
while (killme != null) {
try {
Thread.sleep(speed);
} catch (InterruptedException e) {}
repaint();
}
killme=null;
}
/**
* paint the current generation
* @param g - destination graphics object
*/
public void paint(Graphics g) {
LifeList.paintAll(g);
}
/**
* override update to avoid erase flicker
* @param g - destination graphics object
*/
public void update(Graphics g) {
if (generating || stepsleft- > 0) {
LifeList.generate(g);
LifeList.updateStatusLine(g);
}
}
}