home *** CD-ROM | disk | FTP | other *** search
Java Source | 1996-07-10 | 11.8 KB | 394 lines |
- import java.applet.Applet;
- import java.awt.*;
- import java.awt.image.ColorModel;
- import java.awt.image.MemoryImageSource;
- import java.lang.InterruptedException;
-
- // DitherTest - this is the applet itself
- public class DitherTest extends Applet implements Runnable {
-
- // these represent color "methods" referred to throughout
- // the program (NOOP means don't change color)
- final static int NOOP = 0;
- final static int RED = 1;
- final static int GREEN = 2;
- final static int BLUE = 3;
- final static int ALPHA = 4;
- final static int SATURATION = 5;
-
- Thread kicker;
-
- // controls for the x and y dimensions (this tells the
- // the application which color to vary and the range)
- DitherControls XControls;
- DitherControls YControls;
-
- // the window in which the color image is displayed
- // (a canvas is a component like a window, except it is
- // not a subclass of container and cannot hold other
- // components)
- DitherCanvas canvas;
-
- // init - read the HTML page for the initial color and
- // ranges and then create the controls and canvas
- public void init() {
- String xspec, yspec;
- int xvals[] = new int[2]; // holds the min and max x vals
- int yvals[] = new int[2]; // holds the min and max y vals
-
- // the following reads the initial x and y ranges and
- // colors from the HTML page (the default x color is red and
- // the default y color is blue)
- try {
- xspec = getParameter("xaxis");
- } catch (Exception e) {
- xspec = null;
- }
- try {
- yspec = getParameter("yaxis");
- } catch (Exception e) {
- yspec = null;
- }
- if (xspec == null) xspec = "red";
- if (yspec == null) yspec = "blue";
- int xmethod = colormethod(xspec, xvals);
- int ymethod = colormethod(yspec, yvals);
-
- // put buttons across the top and bottom; add a New Image
- // (render) button to the bottom controls
- setLayout(new BorderLayout());
- XControls = new DitherControls(this, xvals[0], xvals[1],
- xmethod, false);
- YControls = new DitherControls(this, yvals[0], yvals[1],
- ymethod, true);
- YControls.addRenderButton();
- add("North", XControls);
- add("South", YControls);
-
- // now put the canvas in the middle
- add("Center", canvas = new DitherCanvas());
- }
-
- // start - build the palette in a background thread to
- // avoid locking up the browser for long periods
- public synchronized void start() {
- if (canvas.getImage() == null) {
- kicker = new Thread(this);
- kicker.start();
- }
- }
-
- public synchronized void stop() {
- try {
- if (kicker != null) {
- kicker.stop();
- }
- } catch (Exception e) {
- }
- kicker = null;
- }
-
- public void restart() {
- stop();
- canvas.setImage(null);
- start();
- }
-
- // main - same sort of thing as before - make it so the
- // applet can execute as an application
- public static void main(String args[]) {
- Frame f = new Frame("ArcTest");
- DitherTest ditherTest = new DitherTest();
-
- ditherTest.init();
-
- f.add("Center", ditherTest);
- f.pack();
- f.show();
-
- ditherTest.start();
- }
-
- // colormethod - parse the string s into color and ranges
- int colormethod(String s, int vals[]) {
- int method = NOOP;
-
- if (s == null)
- s = "";
-
- String lower = s.toLowerCase();
- int len = 0;
- if (lower.startsWith("red")) {
- method = RED;
- lower = lower.substring(3);
- } else if (lower.startsWith("green")) {
- method = GREEN;
- lower = lower.substring(5);
- } else if (lower.startsWith("blue")) {
- method = BLUE;
- lower = lower.substring(4);
- } else if (lower.startsWith("alpha")) {
- method = ALPHA;
- lower = lower.substring(4);
- } else if (lower.startsWith("saturation")) {
- method = SATURATION;
- lower = lower.substring(10);
- }
-
- if (method == NOOP) {
- vals[0] = 0;
- vals[1] = 0;
- return method;
- }
-
- int begval = 0;
- int endval = 255;
-
- try {
- int dash = lower.indexOf('-');
- if (dash < 0) {
- begval = endval = Integer.parseInt(lower);
- } else {
- begval = Integer.parseInt(lower.substring(0, dash));
- endval = Integer.parseInt(lower.substring(dash+1));
- }
- } catch (Exception e) {
- }
-
- if (begval < 0) begval = 0;
- if (endval < 0) endval = 0;
- if (begval > 255) begval = 255;
- if (endval > 255) endval = 255;
-
- vals[0] = begval;
- vals[1] = endval;
-
- return method;
- }
-
- // applymethod - create a color pixel in the array c given
- // the method (read "color") and vals (read
- // "intensity")
- void applymethod(int c[], // the color of current pixel
- // c[0] - red saturation
- // c[1] - green saturation
- // c[2] - blue saturation
- // c[3] - intensity
- int method, // the color we're building
- int step, // the offset of the pixel
- int total, // the number of pixels
- int vals[]) { // the range of intensity
- if (method == NOOP)
- return;
-
- // calculate the intensity by taking the max - min and
- // multiplying that by how close they are to the beginning
- // or end of the row/column (e.g., if we are in the middle
- // of a row, give this pixel an intensity that is halfway
- // between the maximum and minimum intensity)
- int val = ((total < 2)
- ? vals[0]
- : vals[0] + ((vals[1] - vals[0])
- * step / (total - 1)));
-
- // now apply this intensity to the color specified by the
- // method; leave the other colors alone
- switch (method) {
- case RED:
- c[0] = val;
- break;
- case GREEN:
- c[1] = val;
- break;
- case BLUE:
- c[2] = val;
- break;
- case ALPHA:
- c[3] = val;
- break;
- case SATURATION:
- int max = Math.max(Math.max(c[0], c[1]), c[2]);
- int min = max * (255 - val) / 255;
- if (c[0] == 0) c[0] = min;
- if (c[1] == 0) c[1] = min;
- if (c[2] == 0) c[2] = min;
- break;
- }
- }
-
- // run - calculate the pixel array and then use it to create
- // the image
- public void run() {
- Thread me = Thread.currentThread();
- me.setPriority(4);
-
- // get the dimensions of the image to produce
- int width = canvas.size().width;
- int height = canvas.size().height;
-
- // read the range and color selection from the horizontal
- // and vertical controls
- int xvals[] = new int[2];
- int yvals[] = new int[2];
- int xmethod = XControls.getParams(xvals);
- int ymethod = YControls.getParams(yvals);
-
- // allocate a pixel array big enough for the canvas
- int pixels[] = new int[width * height];
-
- // create the pixel array for the image
- int c[] = new int[4];
- int index = 0;
- for (int j = 0; j < height; j++) {
- for (int i = 0; i < width; i++) {
- // start with a pixel that has full intensity but no
- // colors (the colors will be added by applymethod)
- c[0] = c[1] = c[2] = 0;
- c[3] = 255;
-
- // calculate the color of each pixel
- if (xmethod < ymethod) {
- applymethod(c, xmethod, i, width, xvals);
- applymethod(c, ymethod, j, height, yvals);
- } else {
- applymethod(c, ymethod, j, height, yvals);
- applymethod(c, xmethod, i, width, xvals);
- }
-
- // now pack the color array into a single 32-bit value
- // the way MemoryImageSource expects it
- pixels[index++] = ((c[3] << 24) | // intensity
- (c[0] << 16) | // red
- (c[1] << 8) | // green
- (c[2] << 0)); // blue
- if (kicker != me) {
- return;
- }
- }
- }
-
- // create an image out of the resulting pixel array
- newImage(me, width, height, pixels);
- }
-
- // newImage - create an image out of the pixel array by
- // using the MemoryImageSource class
- synchronized void newImage(Thread me,
- int width, int height,
- int pixels[]) {
- if (kicker != me) {
- return;
- }
- Image img;
- img = createImage(new MemoryImageSource(width, height,
- ColorModel.getRGBdefault(),
- pixels, 0, width));
- canvas.setImage(img);
- kicker = null;
- }
- }
-
- // DitherCanvas provides the canvas into which the calculated
- // image is displayed
- class DitherCanvas extends Canvas {
- Image img;
- static String calcString = "Calculating...";
-
- public void paint(Graphics g) {
- int w = size().width;
- int h = size().height;
- if (img == null) {
- super.paint(g);
- g.setColor(Color.black);
- FontMetrics fm = g.getFontMetrics();
- int x = (w - fm.stringWidth(calcString))/2;
- int y = h/2;
- g.drawString(calcString, x, y);
- } else {
- g.drawImage(img, 0, 0, w, h, this);
- }
- }
-
- public Dimension minimumSize() {
- return new Dimension(20, 20);
- }
-
- public Dimension preferredSize() {
- return new Dimension(200, 200);
- }
-
- public Image getImage() {
- return img;
- }
-
- public void setImage(Image img) {
- this.img = img;
- repaint();
- }
- }
-
- // DitherControls provides the x and y control widgets that
- // the user can use to select what colors to vary and
- // by how much (from what to what)
- class DitherControls extends Panel {
- TextField start;
- TextField end;
- Button button;
- Choice choice;
- DitherTest applet;
-
- static LayoutManager dcLayout = new
- FlowLayout(FlowLayout.CENTER, 10, 5);
-
- public DitherControls(DitherTest app,
- int s, int e, int type, // initial start, end, and color
- boolean vertical) { // vertical or horizontal control
- applet = app;
- setLayout(dcLayout);
- add(new Label(vertical ? "Vertical" : "Horizontal"));
-
- // a choice is a drop-down menu
- add(choice = new Choice());
- choice.addItem("Noop");
- choice.addItem("Red");
- choice.addItem("Green");
- choice.addItem("Blue");
- choice.addItem("Alpha");
- choice.addItem("Saturation");
-
- // now set the controls to their initial value
- choice.select(type);
- add(start = new TextField(Integer.toString(s), 4));
- add(end = new TextField(Integer.toString(e), 4));
- }
-
- // addRenderButton - called to add the New Image button to
- // one of the controls (you don't need it
- // twice)
- public void addRenderButton() {
- add(button = new Button("New Image"));
- }
-
- // getParams - read the control widget. store the min
- // and max color range in vals[] and return
- // the item selected as an integer offset.
- public int getParams(int vals[]) {
- vals[0] = Integer.parseInt(start.getText());
- vals[1] = Integer.parseInt(end.getText());
- return choice.getSelectedIndex();
- }
-
- // action - when the user clicks the "New Image" button
- // tell the applet to restart. the applet will
- // read the widgets using the getParams method.
- public boolean action(Event ev, Object arg) {
- if (ev.target instanceof Button) {
- applet.restart();
-
- return true;
- }
-
- return false;
- }
- }
-