home *** CD-ROM | disk | FTP | other *** search
/ Learn Java Now / Learn_Java_Now_Microsoft_1996.iso / JavaNow / Code / AppB / DitherTest / DitherTest.java < prev    next >
Encoding:
Java Source  |  1996-07-10  |  11.8 KB  |  394 lines

  1. import java.applet.Applet;
  2. import java.awt.*;
  3. import java.awt.image.ColorModel;
  4. import java.awt.image.MemoryImageSource;
  5. import java.lang.InterruptedException;
  6.  
  7. // DitherTest - this is the applet itself
  8. public class DitherTest extends Applet implements Runnable {
  9.  
  10.     // these represent color "methods" referred to throughout
  11.     // the program (NOOP means don't change color)
  12.     final static int NOOP = 0;
  13.     final static int RED = 1;
  14.     final static int GREEN = 2;
  15.     final static int BLUE = 3;
  16.     final static int ALPHA = 4;
  17.     final static int SATURATION = 5;
  18.  
  19.     Thread kicker;
  20.  
  21.     // controls for the x and y dimensions (this tells the
  22.     // the application which color to vary and the range)
  23.     DitherControls XControls;
  24.     DitherControls YControls;
  25.  
  26.     // the window in which the color image is displayed
  27.     // (a canvas is a component like a window, except it is 
  28.     // not a subclass of container and cannot hold other
  29.     // components)
  30.     DitherCanvas canvas;
  31.  
  32.     // init - read the HTML page for the initial color and
  33.     //          ranges and then create the controls and canvas
  34.     public void init() {
  35.     String xspec, yspec;
  36.     int xvals[] = new int[2]; // holds the min and max x vals
  37.     int yvals[] = new int[2]; // holds the min and max y vals
  38.  
  39.     // the following reads the initial x and y ranges and
  40.     // colors from the HTML page (the default x color is red and
  41.     // the default y color is blue)
  42.     try {
  43.         xspec = getParameter("xaxis");
  44.     } catch (Exception e) {
  45.         xspec = null;
  46.     }
  47.     try {
  48.         yspec = getParameter("yaxis");
  49.     } catch (Exception e) {
  50.         yspec = null;
  51.     }
  52.     if (xspec == null) xspec = "red";
  53.     if (yspec == null) yspec = "blue";
  54.     int xmethod = colormethod(xspec, xvals);
  55.     int ymethod = colormethod(yspec, yvals);
  56.  
  57.     // put buttons across the top and bottom; add a New Image
  58.     // (render) button to the bottom controls
  59.     setLayout(new BorderLayout());
  60.     XControls = new DitherControls(this, xvals[0], xvals[1],
  61.                        xmethod, false);
  62.     YControls = new DitherControls(this, yvals[0], yvals[1],
  63.                        ymethod, true);
  64.     YControls.addRenderButton();
  65.     add("North", XControls);
  66.     add("South", YControls);
  67.  
  68.     // now put the canvas in the middle
  69.     add("Center", canvas = new DitherCanvas());
  70.     }
  71.  
  72.     // start - build the palette in a background thread to 
  73.     // avoid locking up the browser for long periods
  74.     public synchronized void start() {
  75.     if (canvas.getImage() == null) {
  76.         kicker = new Thread(this);
  77.         kicker.start();
  78.     }
  79.     }
  80.  
  81.     public synchronized void stop() {
  82.     try {
  83.         if (kicker != null) {
  84.         kicker.stop();
  85.         }
  86.     } catch (Exception e) {
  87.     }
  88.     kicker = null;
  89.     }
  90.  
  91.     public void restart() {
  92.     stop();
  93.     canvas.setImage(null);
  94.     start();
  95.     }
  96.  
  97.     // main - same sort of thing as before - make it so the
  98.     // applet can execute as an application
  99.     public static void main(String args[]) {
  100.     Frame f = new Frame("ArcTest");
  101.     DitherTest    ditherTest = new DitherTest();
  102.  
  103.     ditherTest.init();
  104.  
  105.     f.add("Center", ditherTest);
  106.     f.pack();
  107.     f.show();
  108.  
  109.     ditherTest.start();
  110.     }
  111.  
  112.     // colormethod - parse the string s into color and ranges
  113.     int colormethod(String s, int vals[]) {
  114.     int method = NOOP;
  115.  
  116.     if (s == null)
  117.         s = "";
  118.  
  119.     String lower = s.toLowerCase();
  120.     int len = 0;
  121.     if (lower.startsWith("red")) {
  122.         method = RED;
  123.         lower = lower.substring(3);
  124.     } else if (lower.startsWith("green")) {
  125.         method = GREEN;
  126.         lower = lower.substring(5);
  127.     } else if (lower.startsWith("blue")) {
  128.         method = BLUE;
  129.         lower = lower.substring(4);
  130.     } else if (lower.startsWith("alpha")) {
  131.         method = ALPHA;
  132.         lower = lower.substring(4);
  133.     } else if (lower.startsWith("saturation")) {
  134.         method = SATURATION;
  135.         lower = lower.substring(10);
  136.     }
  137.  
  138.     if (method == NOOP) {
  139.         vals[0] = 0;
  140.         vals[1] = 0;
  141.         return method;
  142.     }
  143.  
  144.     int begval = 0;
  145.     int endval = 255;
  146.  
  147.     try {
  148.         int dash = lower.indexOf('-');
  149.         if (dash < 0) {
  150.         begval = endval = Integer.parseInt(lower);
  151.         } else {
  152.         begval = Integer.parseInt(lower.substring(0, dash));
  153.         endval = Integer.parseInt(lower.substring(dash+1));
  154.         }
  155.     } catch (Exception e) {
  156.     }
  157.  
  158.     if (begval < 0) begval = 0;
  159.     if (endval < 0) endval = 0;
  160.     if (begval > 255) begval = 255;
  161.     if (endval > 255) endval = 255;
  162.  
  163.     vals[0] = begval;
  164.     vals[1] = endval;
  165.  
  166.     return method;
  167.     }
  168.  
  169.     // applymethod - create a color pixel in the array c given
  170.     //               the method (read "color") and vals (read
  171.     //               "intensity")
  172.     void applymethod(int c[],       // the color of current pixel
  173.                                     // c[0] - red saturation
  174.                                     // c[1] - green saturation
  175.                                     // c[2] - blue saturation
  176.                                     // c[3] - intensity
  177.                      int method,    // the color we're building
  178.                      int step,      // the offset of the pixel
  179.                      int total,     // the number of pixels
  180.                      int vals[]) {  // the range of intensity
  181.     if (method == NOOP)
  182.         return;
  183.  
  184.     // calculate the intensity by taking the max - min and
  185.     // multiplying that by how close they are to the beginning
  186.     // or end of the row/column (e.g., if we are in the middle
  187.     // of a row, give this pixel an intensity that is halfway
  188.     // between the maximum and minimum intensity)
  189.     int val = ((total < 2)
  190.            ? vals[0]
  191.            : vals[0] + ((vals[1] - vals[0])
  192.                                         * step / (total - 1)));
  193.  
  194.     // now apply this intensity to the color specified by the
  195.     // method; leave the other colors alone
  196.     switch (method) {
  197.     case RED:
  198.         c[0] = val;
  199.         break;
  200.     case GREEN:
  201.         c[1] = val;
  202.         break;
  203.     case BLUE:
  204.         c[2] = val;
  205.         break;
  206.     case ALPHA:
  207.         c[3] = val;
  208.         break;
  209.     case SATURATION:
  210.         int max = Math.max(Math.max(c[0], c[1]), c[2]);
  211.         int min = max * (255 - val) / 255;
  212.         if (c[0] == 0) c[0] = min;
  213.         if (c[1] == 0) c[1] = min;
  214.         if (c[2] == 0) c[2] = min;
  215.         break;
  216.     }
  217.     }
  218.  
  219.     // run - calculate the pixel array and then use it to create
  220.     //       the image
  221.     public void run() {
  222.     Thread me = Thread.currentThread();
  223.     me.setPriority(4);
  224.  
  225.     // get the dimensions of the image to produce
  226.     int width = canvas.size().width;
  227.     int height = canvas.size().height;
  228.  
  229.     // read the range and color selection from the horizontal
  230.     // and vertical controls
  231.     int xvals[] = new int[2];
  232.     int yvals[] = new int[2];
  233.     int xmethod = XControls.getParams(xvals);
  234.     int ymethod = YControls.getParams(yvals);
  235.  
  236.     // allocate a pixel array big enough for the canvas
  237.     int pixels[] = new int[width * height];
  238.  
  239.     // create the pixel array for the image
  240.     int c[] = new int[4];
  241.     int index = 0;
  242.     for (int j = 0; j < height; j++) {
  243.         for (int i = 0; i < width; i++) {
  244.         // start with a pixel that has full intensity but no
  245.         // colors (the colors will be added by applymethod)
  246.         c[0] = c[1] = c[2] = 0;
  247.         c[3] = 255;
  248.  
  249.         // calculate the color of each pixel
  250.         if (xmethod < ymethod) {
  251.             applymethod(c, xmethod, i, width, xvals);
  252.             applymethod(c, ymethod, j, height, yvals);
  253.         } else {
  254.             applymethod(c, ymethod, j, height, yvals);
  255.             applymethod(c, xmethod, i, width, xvals);
  256.         }
  257.  
  258.         // now pack the color array into a single 32-bit value
  259.         // the way MemoryImageSource expects it
  260.         pixels[index++] = ((c[3] << 24) |  // intensity
  261.                    (c[0] << 16) |          // red
  262.                    (c[1] << 8) |           // green
  263.                    (c[2] << 0));           // blue
  264.         if (kicker != me) {
  265.             return;
  266.         }
  267.         }
  268.     }
  269.  
  270.     // create an image out of the resulting pixel array
  271.     newImage(me, width, height, pixels);
  272.     }
  273.  
  274.     // newImage - create an image out of the pixel array by 
  275.     // using the MemoryImageSource class
  276.     synchronized void newImage(Thread me,
  277.                                int width, int height,
  278.                                int pixels[]) {
  279.     if (kicker != me) {
  280.         return;
  281.     }
  282.     Image img;
  283.     img = createImage(new MemoryImageSource(width, height,
  284.                         ColorModel.getRGBdefault(),
  285.                         pixels, 0, width));
  286.     canvas.setImage(img);
  287.     kicker = null;
  288.     }
  289. }
  290.  
  291. // DitherCanvas provides the canvas into which the calculated
  292. // image is displayed
  293. class DitherCanvas extends Canvas {
  294.     Image img;
  295.     static String calcString = "Calculating...";
  296.  
  297.     public void paint(Graphics g) {
  298.     int w = size().width;
  299.     int h = size().height;
  300.     if (img == null) {
  301.         super.paint(g);
  302.         g.setColor(Color.black);
  303.         FontMetrics fm = g.getFontMetrics();
  304.         int x = (w - fm.stringWidth(calcString))/2;
  305.         int y = h/2;
  306.         g.drawString(calcString, x, y);
  307.     } else {
  308.         g.drawImage(img, 0, 0, w, h, this);
  309.     }
  310.     }
  311.  
  312.     public Dimension minimumSize() {
  313.     return new Dimension(20, 20);
  314.     }
  315.  
  316.     public Dimension preferredSize() {
  317.     return new Dimension(200, 200);
  318.     }
  319.  
  320.     public Image getImage() {
  321.     return img;
  322.     }
  323.  
  324.     public void setImage(Image img) {
  325.     this.img = img;
  326.     repaint();
  327.     }
  328. }
  329.  
  330. // DitherControls provides the x and y control widgets that
  331. // the user can use to select what colors to vary and
  332. // by how much (from what to what)
  333. class DitherControls extends Panel {
  334.     TextField start;
  335.     TextField end;
  336.     Button button;
  337.     Choice choice;
  338.     DitherTest applet;
  339.  
  340.     static LayoutManager dcLayout = new
  341.                             FlowLayout(FlowLayout.CENTER, 10, 5);
  342.  
  343.     public DitherControls(DitherTest app,
  344.         int s, int e, int type, // initial start, end, and color
  345.         boolean vertical) {     // vertical or horizontal control
  346.     applet = app;
  347.     setLayout(dcLayout);
  348.     add(new Label(vertical ? "Vertical" : "Horizontal"));
  349.  
  350.     // a choice is a drop-down menu
  351.     add(choice = new Choice());
  352.     choice.addItem("Noop");
  353.     choice.addItem("Red");
  354.     choice.addItem("Green");
  355.     choice.addItem("Blue");
  356.     choice.addItem("Alpha");
  357.     choice.addItem("Saturation");
  358.  
  359.     // now set the controls to their initial value
  360.     choice.select(type);
  361.     add(start = new TextField(Integer.toString(s), 4));
  362.     add(end = new TextField(Integer.toString(e), 4));
  363.     }
  364.  
  365.     // addRenderButton - called to add the New Image button to
  366.     //                   one of the controls (you don't need it
  367.     //                   twice)
  368.     public void addRenderButton() {
  369.     add(button = new Button("New Image"));
  370.     }
  371.  
  372.     // getParams - read the control widget. store the min
  373.     //               and max color range in vals[] and return
  374.     //               the item selected as an integer offset.
  375.     public int getParams(int vals[]) {
  376.     vals[0] = Integer.parseInt(start.getText());
  377.     vals[1] = Integer.parseInt(end.getText());
  378.     return choice.getSelectedIndex();
  379.     }
  380.  
  381.     // action - when the user clicks the "New Image" button
  382.     //            tell the applet to restart. the applet will
  383.     //            read the widgets using the getParams method.
  384.     public boolean action(Event ev, Object arg) {
  385.     if (ev.target instanceof Button) {
  386.         applet.restart();
  387.  
  388.         return true;
  389.     }
  390.  
  391.     return false;
  392.     }
  393. }
  394.