| In the previous fractal demonstration 
              program we drew each point of the display with the graphics 
              context methods. This involves invocations of the drawLine() 
              method for every point in the fractal display area. We demonstrate 
              a faster technique here in which the pixels for a BufferedImage 
              are modified directly and then the image is displayed in a single 
              method invocation. If you compare the performance of the demonstration 
              applet below with the previous applet, 
              you should see a considerable improvement.  The codes are very similar to the preceding case. FractalsImgApplet 
              differs from FractalsApplet 
              only in the list of algorithms. The algorithm classes also are very 
              similar to the classes for the draw 
              demo except that they modify a pixel in a BufferedImage object 
              rather than invoke drawLine(). 
              
              
                 
                  | Demo: Fractals displayed via pixel handling 
                    in a BufferedImage
 
 
  
                      FractalsImgApplet.java 
                         - similar to FractalsApplet 
                        except that it selects from instances of the following 
                        DrawFunction classes to display the fractal patterns. 
 + New Classes:
 DrawBifurcationImg.java
  - DrawFunction subclass that creates a fractal pattern 
                        with the Bifurcation algorithm using the pixels of an 
                        image and then draws the image. DrawJuliaSetImg.java
  - DrawFunction subclass that creates a fractal pattern 
                        with the Julia Set algorithm using the pixels of an image 
                        and then draws the image. DrawJuliaSetNewtonImg.java
  - DrawFunction subclass that creates a fractal pattern 
                        with the Julia Set via Newton's method algorithm using 
                        the pixels of an image and then draws the image. DrawMandlebrotImg.java
  - DrawFunction subclass that creates a fractal pattern 
                        with the Mandlebrot algorithm using the pixels of an image 
                        and then draws the image. 
 + Previous classes:
 FractalController.java, 
                        FractalPanel.java,
 MousePlotPanel.java, MouseHandler.java
 Chapter 
                        6:Tech: PlotPanel.java, 
                        PlotFormat.java
 Chapter 
                        6:Tech:  DrawFunction.java
 Chapter 
                        4:Tech: Complex.java
   |   
                  | // 
                    Begin from StarterJApplet11 
 import javax.swing.*;
 import java.awt.*;
 import java.awt.event.*;
 import javax.swing.event.*;
 
 
 /**
 *  Demonstrate various fractal algorithms. 
                    User selects
 *  from a list of algorithms. Graphical 
                    output of the
 *  algorithm is displayed within a plot 
                    frame using a
 *  subclass of MousePlotPanel, which 
                    in turn is a subclass
 *  of PlotPanel.
 
 *
 *  The fractal algorithms are included 
                    in DrawFunction
 *  subclasses. They create the fractal 
                    patterns by modifying
 *  image pixel data and then drawing 
                    the image with the
 *  graphics context object passed to 
                    it.
 
 *
 *  The user can drag the cursor to outline 
                    a rectangle
 *  whose dimensions are used for a rescaled 
                    graph. The
 *  MousePlotPanel provides the mouse 
                    event information.
 
 *
 *  The class implement the FractalController 
                    interface so that the
 *  FractalPanel object can call back 
                    to send new dimensions
 *  for the graph area. It also calls 
                    back to indicate when
 *  fractal generation is happening so 
                    that the controls
 *  can be put into a busy state and 
                    not interfere with the
 *  operation.
 **/
 public class FractalsImgApplet extends JApplet
 implements ActionListener, 
                    ListSelectionListener,
 FractalController
 {
 // Flag to indicate if the applet is in a browser
 // or running as an application via the main () 
                    method.
 boolean fInBrowser = true;
 
 // Fractal panel can display different algorithms 
                    by
 // passing to it a new DrawFractal object.
 FractalPanel fOutputPanel;
 
 // A text field for input strings
 JTextField fFieldXLeft, fFieldXRite, fFieldYTop, 
                    fFieldYBot;
 
 // Parameters for the algorithms.
 double fParam0 = 0.0;
 double fParam1 = 0.0;
 
 // Text fields to input the algorithm parameters
 JTextField fFieldParam0;
 JTextField fFieldParam1;
 
 // Labels for the parameters
 JLabel fLabelParam0, fLabelParam1;
 
 // A number to indicate the selected algorithm.
 int fAlgorithm = ALG_BIFURCATION;
 
 // Define a set of constants to specify a given 
                    algorithm
 final static int ALG_BIFURCATION   = 
                    0;
 final static int ALG_JULIASET      = 
                    1;
 final static int ALG_JULIASET_NEWT = 2;
 final static int ALG_MANDLEBROT    = 
                    3;
 
 // Default dimensions according to the algorithm
 double [][] fXYDef =
 {
 {-2.0, 2.0, 
                    -2.0, 2.0}, // Bifurcation
 {-2.0, 2.0, 
                    -2.0, 2.0}, // Julia set
 {-3.0, 3.0, 
                    -3.0, 3.0}, // Julia set from Newton's method
 {-2.5, 2.5, 
                    -2.5, 2.5}  // Mandlebrot
 };
 
 // Hold the default algorithm parameters in this 
                    2-d array.
 double [][] fAlgorithmParams = {
 {0.0,  0.0}, 
                    // Bifurcation
 {0.36, 
                    0.25},// Julia set
 {0.0,  0.0}, 
                    // Julia set from Newton's method
 {0.0,  0.0}  // 
                    Mandlebrot
 };
 
 // List component for the algorithms.
 JList fAlgorithmJList;
 String [] fAlgorithmList = {"Bifurcation",
 "Julia 
                    Set",
 "Julia 
                    Set- Newton's",
 "Mandlebrot"
 };
 
 
 // Keep an array of the fractal generators
 DrawFunction [] drawFractals = new DrawFunction[4];
 
 // Need a button to return to the default dimensions.
 JButton fResetButton;
 
 /**
 * Create a User Interface with four 
                    fields that show the
 * current dimensions of the fractal 
                    graphing area.
 * The interface also includes a JList 
                    with the
 * list of algorithms. Selecting one 
                    will initiate the
 * algorithm. A "Reset" button will 
                    return the dimensions to
 * the default values and redraw the 
                    graph.
 **/
 public void init () {
 
 JPanel panel = new JPanel (new BorderLayout 
                    ());
 
 // When user hits reset button, the 
                    graph will be
 // redrawn with default dimensions.
 fResetButton = new JButton ("Reset");
 fResetButton.addActionListener (this);
 
 // Use a textfield for an input parameter.
 fFieldXLeft = new JTextField (Double.toString 
                    (fXYDef[0][0]), 6);
 fFieldXRite = new JTextField (Double.toString 
                    (fXYDef[0][1]), 6);
 fFieldYBot  = new JTextField 
                    (Double.toString (fXYDef[0][2]), 6);
 fFieldYTop  = new JTextField 
                    (Double.toString (fXYDef[0][3]), 6);
 
 // Use a GridLayout to show the dimensions
 JPanel dim_labels_panel = new JPanel 
                    (new GridLayout (2,1));
 dim_labels_panel.add (new JLabel ("X 
                    = ", SwingConstants.RIGHT));
 dim_labels_panel.add (new JLabel ("Y 
                    = ", SwingConstants.RIGHT));
 
 JPanel dimensions_panel = new JPanel 
                    (new GridLayout (2,2));
 dimensions_panel.add (fFieldXLeft);
 dimensions_panel.add (fFieldXRite);
 dimensions_panel.add (fFieldYBot);
 dimensions_panel.add (fFieldYTop);
 
 // Parameters fields
 fFieldParam0 = new JTextField (Double.toString 
                    (fParam0),6);
 fFieldParam1 = new JTextField (Double.toString 
                    (fParam1),6);
 JPanel parameters_panel = new JPanel 
                    (new GridLayout (2,2));
 fLabelParam0 = new JLabel ("P0 = ", 
                    SwingConstants.RIGHT);
 parameters_panel.add (fLabelParam0);
 parameters_panel.add (fFieldParam0);
 fLabelParam1 = new JLabel ("P1 = ", 
                    SwingConstants.RIGHT);
 parameters_panel.add (fLabelParam1);
 parameters_panel.add (fFieldParam1);
 
 // Combine the panels for the dimensions, 
                    their labels
 // and parameters  onto 
                    one panel.
 JPanel dim_param_panel = new JPanel 
                    ();
 dim_param_panel.add (dim_labels_panel);
 dim_param_panel.add (dimensions_panel);
 dim_param_panel.add (parameters_panel);
 
 // Create a JList for the algorithms.
 fAlgorithmJList = new JList (fAlgorithmList);
 
 // Show only the current algorithm
 fAlgorithmJList.setVisibleRowCount 
                    (2);
 
 // Allow only one of the items to 
                    be selected.
 fAlgorithmJList.setSelectionMode (
 ListSelectionModel.SINGLE_SELECTION);
 
 // Select initially the top item.
 fAlgorithmJList.setSelectedIndex (ALG_BIFURCATION);
 
 // Send selection events to this object.
 fAlgorithmJList.addListSelectionListener 
                    (this);
 
 // Add the list to a JScrollPane so 
                    that we can
 // scroll to view other items.
 JScrollPane list_scroll_pane = new 
                    JScrollPane (fAlgorithmJList);
 
 // Create a panel to hold the controls.
 JPanel control_panel = new JPanel 
                    ();
 control_panel.add (dim_param_panel);
 control_panel.add (list_scroll_pane);
 control_panel.add (fResetButton);
 
 // And combine it with the FractalPanel.
 panel.add (control_panel,"South");
 
 // Create the bifurcation algorithm 
                    as the first choice.
 drawFractals[ALG_BIFURCATION] = new 
                    DrawBifurcationImg ();
 
 // Only need one parameter for the 
                    bifurcation algorithm
 fLabelParam1.setEnabled (false);
 fFieldParam1.setEnabled (false);
 
 // Add the algorithm panel here.
 fOutputPanel = new FractalPanel (this, 
                    drawFractals[0],
 fXYDef[fAlgorithm][0],
 fXYDef[fAlgorithm][1],
 fXYDef[fAlgorithm][2],
 fXYDef[fAlgorithm][3]);
 
 panel.add (fOutputPanel,"Center");
 
 // Then add this panel to the applet.
 add (panel);
 
 } // init
 
 /**
 * Implementation of FractalController 
                    interface: This method
 * provides for callbacks from the 
                    FractalPanel with the new
 * dimensions for the area to plot.
 *
 **/
 public void setFractalParameters (double x_min, 
                    double x_max,
 double 
                    y_min, double y_max) {
 // Reset dimensions to defaults.
 fFieldXLeft.setText (PlotFormat.getFormatted 
                    (x_min, 100.0, 1000.0, 3));
 fFieldXRite.setText (PlotFormat.getFormatted 
                    (x_max, 100.0, 1000.0, 3));
 fFieldYBot.setText  (PlotFormat.getFormatted 
                    (y_min, 100.0, 1000.0, 3));
 fFieldYTop.setText  (PlotFormat.getFormatted 
                    (y_max, 100.0, 1000.0, 3));
 } // setFractalParameters
 
 
 /**
 * Implementation of FractalController 
                    interface: This method
 * provides the values in the text 
                    fields for the parameters
 * needed by a given algorithm.
 **/
 public void getFractalParameters (double [] parameters) 
                    {
 
 if (fAlgorithm == ALG_BIFURCATION) 
                    {
 try {
 fParam0 = 
                    Double.valueOf (fFieldParam0.getText ());
 } catch (NumberFormatException 
                    nfe) {
 fParam0 = 
                    fAlgorithmParams[ALG_BIFURCATION][0];
 fFieldParam0.setText 
                    ("0.0");
 }
 parameters[2] = fParam0;
 
 } else
 if (fAlgorithm == ALG_JULIASET) { 
                    // Julia Set
 try {
 fParam0 = 
                    Double.valueOf (fFieldParam0.getText ());
 fParam0 = 
                    Double.valueOf (fFieldParam0.getText ());
 } catch (NumberFormatException 
                    nfe) {
 fParam0 = 
                    fAlgorithmParams[ALG_JULIASET][0];
 fParam1 = 
                    fAlgorithmParams[ALG_JULIASET][1];
 fFieldParam0.setText 
                    (Double.toString (fParam0));
 }
 parameters[2] = fParam0;
 parameters[3] = fParam1;
 } else
 if (fAlgorithm == ALG_JULIASET_NEWT 
                    ||
 fAlgorithm 
                    == ALG_MANDLEBROT ) { // Julia Set - Newton's method
 // or Mandlebrot
 }
 
 } // getFractalParameters
 
 
 /**
 * Implementation of FractalController 
                    interface: This method
 * turns off controls while fractal 
                    generation runs. It turns
 * them back on when the generation 
                    is done.
 **/
 public void setBusy (boolean flag) {
 
 if (flag) {
 fResetButton.setEnabled 
                    (false);
 fAlgorithmJList.setEnabled 
                    (false);
 if (fAlgorithm 
                    == ALG_BIFURCATION ||
 fAlgorithm 
                    == ALG_JULIASET) {
 fFieldParam0.setEnabled (false);
 fLabelParam0.setEnabled (false);
 }
 if (fAlgorithm 
                    == ALG_JULIASET) {
 fFieldParam1.setEnabled 
                    (false);
 fLabelParam1.setEnabled 
                    (false);
 }
 fResetButton.setText 
                    ("BUSY");
 } else {
 fResetButton.setEnabled 
                    (true);
 fAlgorithmJList.setEnabled 
                    (true);
 if (fAlgorithm 
                    == ALG_BIFURCATION ||
 fAlgorithm 
                    == ALG_JULIASET) {
 fFieldParam0.setEnabled (true);
 fLabelParam0.setEnabled (true);
 }
 if (fAlgorithm 
                    == ALG_JULIASET) {
 fFieldParam1.setEnabled 
                    (true);
 fLabelParam1.setEnabled 
                    (true);
 }
 fResetButton.setText 
                    ("Reset");
 }
 } // setBusy
 
 
 /**
 * Reset button will reset the drawing 
                    area back to
 * the default dimensions.
 **/
 public void actionPerformed (ActionEvent e)
 {
 Object source = e.getSource ();
 if (source == fResetButton) {
 // Reset dimensions 
                    to defaults
 resetDefaultFrame 
                    ();
 fOutputPanel.setRange 
                    (fXYDef[fAlgorithm][0],
 fXYDef[fAlgorithm][1],
 fXYDef[fAlgorithm][2],
 fXYDef[fAlgorithm][3]);
 }
 } // actionPerformed
 
 
 /** Reset the frame to the default dimensions. 
                    **/
 public void resetDefaultFrame ()
 {
 // Reset dimensions to defaults
 fFieldXLeft.setText (Double.toString 
                    (fXYDef[fAlgorithm][0]));
 fFieldXRite.setText (Double.toString 
                    (fXYDef[fAlgorithm][1]));
 fFieldYBot.setText  (Double.toString 
                    (fXYDef[fAlgorithm][2]));
 fFieldYTop.setText  (Double.toString 
                    (fXYDef[fAlgorithm][3]));
 } // resetDefaultFrame
 
 
 /**
 * User selects an algorithm from the 
                    JList.
 **/
 public void valueChanged (ListSelectionEvent evt)  {
 
 // Get the reference to the JList 
                    object
 JList source =  (JList)evt.getSource 
                    ();
 
 // and get an array of the selected 
                    items.
 Object [] values = source.getSelectedValues 
                    ();
 
 // In this case only one value can 
                    be selected
 // so just look at first item in array.
 String algorithm_selected =  (String)values[0];
 
 // Set the title accordingly
 fOutputPanel.setTitle (algorithm_selected);
 
 // For the selected algorithm, pass 
                    it to the FractalPanel
 // and also set up the parameter elements 
                    on the user interface.
 
 if (algorithm_selected.equals (fAlgorithmList[ALG_BIFURCATION])) 
                    {
 // Only need 
                    one parameter for the bifurcation algorithm
 fLabelParam1.setEnabled 
                    (false);
 fFieldParam1.setEnabled 
                    (false);
 fAlgorithm 
                    = ALG_BIFURCATION;
 fParam0 = 
                    fAlgorithmParams[fAlgorithm][0];
 fFieldParam0.setText 
                    (Double.toString (fParam0));
 fFieldParam1.setText 
                    (" ");
 } else
 if (algorithm_selected.equals (fAlgorithmList[ALG_JULIASET])) 
                    {
 // Need two 
                    parameters for the Julia set algorithm
 fLabelParam1.setEnabled 
                    (true);
 fFieldParam1.setEnabled 
                    (true);
 fAlgorithm 
                    = ALG_JULIASET;
 fParam0 = 
                    fAlgorithmParams[fAlgorithm][0];
 fParam1 = 
                    fAlgorithmParams[fAlgorithm][1];
 fFieldParam0.setText 
                    (Double.toString (fParam0));
 fFieldParam1.setText 
                    (Double.toString (fParam1));
 // Reset back 
                    to the default frame scale
 resetDefaultFrame 
                    ();
 // Get the 
                    algorithm
 if (drawFractals[fAlgorithm] 
                    == null)
 drawFractals[fAlgorithm] = new DrawJuliaSetImg ();
 } else
 if (algorithm_selected.equals (fAlgorithmList[ALG_JULIASET_NEWT])) 
                    {
 // No parameters 
                    used for the Julia set from Newton's method
 fLabelParam0.setEnabled 
                    (false);
 fFieldParam0.setEnabled 
                    (false);
 fLabelParam1.setEnabled 
                    (false);
 fFieldParam1.setEnabled 
                    (false);
 fAlgorithm 
                    = ALG_JULIASET_NEWT;
 fFieldParam0.setText 
                    (" ");
 fFieldParam1.setText 
                    (" ");
 // Reset back 
                    to the default frame scale
 resetDefaultFrame 
                    ();
 // Get the 
                    algorithm
 if (drawFractals[fAlgorithm] 
                    == null)
 drawFractals[fAlgorithm] = new DrawJuliaSetNewtonImg ();
 } else
 if (algorithm_selected.equals (fAlgorithmList[ALG_MANDLEBROT])) 
                    {
 // No parameters 
                    used for the Mandlebrot algorithm
 fLabelParam0.setEnabled 
                    (false);
 fFieldParam0.setEnabled 
                    (false);
 fLabelParam1.setEnabled 
                    (false);
 fFieldParam1.setEnabled 
                    (false);
 fAlgorithm 
                    = ALG_MANDLEBROT;
 fFieldParam0.setText 
                    (" ");
 fFieldParam1.setText 
                    (" ");
 // Reset back 
                    to the default frame scale
 resetDefaultFrame 
                    ();
 // Get the 
                    algorithm
 if (drawFractals[ALG_MANDLEBROT] 
                    == null)
 drawFractals[ALG_MANDLEBROT] = new DrawMandlebrotImg ();
 }
 
 // Reset back to the default frame 
                    scale
 resetDefaultFrame ();
 // Pass the new algorithm to the panel
 fOutputPanel.setAlgorithm (drawFractals[fAlgorithm]);
 // Reseting the range will cause the 
                    panel to redraw
 // itself with the new algorithm.
 fOutputPanel.setRange (fXYDef[fAlgorithm][0],
 fXYDef[fAlgorithm][1],
 fXYDef[fAlgorithm][2],
 fXYDef[fAlgorithm][3]);
 
 } // valueChanged
 
 /** Optional application mode. **/
 public static void main (String[] args)  {
 // Frame size.
 int frame_width  = 550;
 int frame_height = 300;
 
 // Add an instance of this applet 
                    to the frame
 FractalsImgApplet applet = new FractalsImgApplet 
                    ();
 applet.fInBrowser = false;
 applet.init ();
 
 // Following anonymous class used 
                    to close window & exit program
 JFrame f = new JFrame ("Fractal Demo 
                    with Images");
 f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
 
 // Add applet to the frame
 f.add (applet);
 f.setSize (new Dimension (frame_width,frame_height));
 f.setVisible (true);
 
 } // main
 
 } // class FractalsImgApplet
 
 
   
 |   
                  | import 
                    java.awt.*; import java.awt.image.*;
 
 /**
 * Create patterns with the bifurcation algorithm 
                    on the drawing context
 * passed to it. The draw() method modifies the 
                    pixels in an image object
 * and then draws that image.
 *
 * The program follows the algorithm as given in 
                    "Java Number Cruncher"
 * by R. Mak.
 *
 * Use a BufferedImage to create the plot.
 **/
 public class DrawBifurcationImg extends DrawFunction
 {
 private static final int MAX_ITERATIONS   
                    = 200;
 private static final int SKIP_INTERATIONS =  50;
 
 /**
 *  Create fractal patterns 
                    with the bifurcation algorithm.
 *  Modify the pixels of 
                    a BufferedImage object and then
 *  draw the image with the 
                    given graphics context.
 *
 *  @param g graphics context
 *  @param frame_width display 
                    area width in pixels.
 *  @param frame_height display 
                    area height in pixels.
 *  @param frame_start_x 
                    horizontal point on display where
 *    drawing starts 
                    in pixel number.
 *  @param frame_start_y 
                    vertical point on display where
 *    drawing starts 
                    in pixel number.
 *  @param x_scale 2 dimensional 
                    array holding lower and
 *    upper values 
                    of the function input scale range.
 *  @param y_scale 2 dimensional 
                    array holding lower and
 *    upper values 
                    of the function output scale range.
 **/
 public void draw (Graphics g,
 int frame_start_x, int frame_start_y,
 int frame_width, int frame_height,
 double [] x_scale, double [] y_scale) {
 
 // Check if ready to draw
 if (fParameters == null) return;
 
 // Create an image on which to create 
                    the plot.
 // Size the image to fit within the 
                    frame
 int img_width  = frame_width  - 
                    1;
 int img_height = frame_height - 1;
 int numPixels = img_width * img_height;
 int [] pixels = new int [numPixels];
 
 // Coordinates in pixel scale
 int row = 0;
 int col = 0;
 int ipx = 0;
 
 // Fill the image with the background 
                    color
 int gray = 0xBB;
 int bg_color = (gray << 16) | (gray 
                    << 8 ) | gray;
 for (row = 0; row < img_height; row++) 
                    {
 for (col = 0; col < img_width; 
                    col++) {
 ipx = col 
                    + row * img_width; // pixel pointer
 pixels[ipx] 
                    = bg_color;
 }
 }
 
 int y_max_index = y_scale.length - 
                    1;
 
 // Get conversion factors from data 
                    scale to frame pixels
 double x_scale_factor = fParameters[0]/frame_width;
 double y_scale_factor = fParameters[1]/frame_height;
 
 
 // Outer loop steps through the c 
                    value along the horizontal axis.
 for (col = 0; col < img_width; col++) 
                    {
 // Change 
                    from pixel scale to the data scale
 double c = 
                    x_scale[0] + col * x_scale_factor;
 double z = 
                    fParameters[2]; // Pass the starting value.
 
 // Now on 
                    this column, plot z along the vertical axis as determined
 // by the 
                    function:
 //   
                    z = z*z + c
 // Plot it 
                    for MAX_ITERATIONS number of times. However, don't start
 // plotting 
                    until after SKIP_ITERATIONS number of times so as to
 // reach the 
                    orbit behavior of the function.
 int red = 
                    0xff << 16;
 for (int i=0; 
                    i < MAX_ITERATIONS; i++) {
 z 
                    = z*z + c;
 if 
                    (i >= SKIP_INTERATIONS) {
 // 
                    Convert from data scale to pixel scale
 row 
                    = (int)Math.round ((y_scale[y_max_index] -
 z)/y_scale_factor);
 if 
                    (row < img_height && row >= 0) {
 ipx = col + row * img_width; // pixel pointer
 pixels[ipx] = red;
 }
 }
 }
 }
 // Create a BufferedIamge of the RGB 
                    type.
 BufferedImage buf_img =
 new BufferedImage (img_width, 
                    img_height, BufferedImage.TYPE_INT_RGB);
 
 // Pass the image the pixel array.
 buf_img.setRGB (0,0,img_width,img_height,pixels,0,img_width);
 
 g.drawImage (buf_img, frame_start_x+1, 
                    frame_start_y+1, null);
 
 } // draw
 
 } // class DrawBifurcationImg
 
 
   |   
                  | import 
                    java.awt.*; import java.awt.image.*;
 
 /**
 * Draw the Julia set algorithm onto the PlotPanel.
 * Follows the algorithm as given in "Java Number 
                    Cruncher"
 * by R. Mak.
 *
 * Use a BufferedImage to create the plot.
 **/
 public class DrawJuliaSetImg extends DrawFunction
 {
 private static final int MAX_ITERATIONS   
                    = 32;
 private static final int ESCAPE_MAGNITUDE =  2;
 
 /**
 *  Execute the Julia set 
                    algorithm onto the PlotPanel.
 *
 *  @param g graphics context
 *  @param frame_width display 
                    area width in pixels.
 *  @param frame_height display 
                    area height in pixels.
 *  @param frame_start_x 
                    horizontal point on display where
 *    drawing starts 
                    in pixel number.
 *  @param frame_start_y 
                    vertical point on display where
 *    drawing starts 
                    in pixel number.
 *  @param x_scale 2 dimensional 
                    array holding lower and
 *    upper values 
                    of the function input scale range.
 *  @param y_scale 2 dimensional 
                    array holding lower and
 *    upper values 
                    of the function output scale range.
 **/
 public void draw (Graphics g,
 int frame_start_x, int frame_start_y,
 int frame_width, int frame_height,
 double [] x_scale, double [] y_scale) {
 
 // Check if ready to draw the line
 if (fParameters == null) return;
 
 int y_max_index = y_scale.length - 
                    1;
 
 // Create an image on which to create 
                    the plot.
 // Size the image to fit within the 
                    frame
 int img_width  = frame_width  - 
                    1;
 int img_height = frame_height - 1;
 int numPixels = img_width * img_height;
 int [] pixels = new int [numPixels];
 
 // Get conversion factors from data 
                    scale to frame pixels
 double x_scale_factor = fParameters[0]/frame_width;
 double y_scale_factor = fParameters[1]/frame_height;
 
 // Obtain the complex constant from 
                    the user interface.
 Complex c = new Complex (fParameters[2], 
                    fParameters[3]);
 Complex z = new Complex (0.0,0.0);
 
 // Coordinates in pixel scale
 int row = 0;
 int col = 0;
 int ipx = 0;
 
 // Outer loop steps through the c 
                    value along the horizontal axis.
 for (row = 0; row < img_height; row++) 
                    {
 // Change 
                    from pixel scale to the data scale
 double y_beg 
                    = y_scale[y_max_index] - row * y_scale_factor;
 
 for (col = 
                    0; col < img_width; col++) {
 ipx 
                    = col + row * img_width; // pixel pointer
 double 
                    x_beg = x_scale[0] + col * x_scale_factor;
 z.real 
                    = x_beg; z.img = y_beg; // Set the starting value.
 
 boolean 
                    escaped = false;
 int 
                    iter   = 0;
 double 
                    x   = x_beg;
 double 
                    y   = y_beg;
 double 
                    mag = 0.0;
 
 // 
                    Iterate the function:
 //   
                    z = z*z + c
 do 
                    {
 z.multiply 
                    (z);
 z.add 
                    (c);
 mag 
                    = z.modulus ();
 escaped 
                    = mag > ESCAPE_MAGNITUDE;
 ++iter;
 } 
                    while (iter < MAX_ITERATIONS && (!escaped));
 
 // 
                    If escaped, then set color to a shade of gray
 // 
                    proportional to the number of interations. The
 // 
                    more iterations, the darker
 if 
                    (escaped) {
 int 
                    gray = 0xFF - (0xFF*iter)/MAX_ITERATIONS;
 gray 
                    = Math.min (gray, 240);
 pixels[ipx] 
                    = (gray << 16) | (gray << 8 ) | gray;
 
 } 
                    else {
 
 // 
                    Did not escape so relate the color instead to the
 // 
                    final magnitude of z.
 
 int 
                    i = ((int)(100*mag)) / ESCAPE_MAGNITUDE + 1;
 int 
                    red = (425*i) & 0xFF;
 int 
                    grn = (375*i) & 0xFF;
 int 
                    blu = (325*i) & 0xFF;
 
 pixels[ipx] 
                    = (red << 16) | (grn << 8 ) | blu;
 }
 }
 }
 // Create a BufferedIamge of the RGB 
                    type.
 BufferedImage buf_img =
 new BufferedImage (img_width, 
                    img_height, BufferedImage.TYPE_INT_RGB);
 
 // Pass the image the pixel array.
 buf_img.setRGB (0,0,img_width,img_height,pixels,0,img_width);
 
 g.drawImage (buf_img, frame_start_x+1, 
                    frame_start_y+1, null);
 
 } // draw
 
 } // class DrawJuliaSetImg
 
 
   
 |   
                  | import 
                    java.awt.*; import java.awt.image.*;
 
 /**
 * Draw the Julia set algorithm onto the PlotPanel.
 * Follows the algorithm given in "Java Number 
                    Cruncher"
 * by R. Mak for solving f(z) = z^3 -1 with Newton's
 * algorithm.
 *
 * Use a BufferedImage to create the plot.
 **/
 public class DrawJuliaSetNewtonImg extends DrawFunction
 {
 private static final int MAX_ITERATIONS   
                    = 100;
 
 // Create two complex constants needed in the 
                    algorthm.
 private static final Complex Z_ONE   
                    = new Complex (1,0);
 private static final Complex Z_THREE = new Complex 
                    (3,0);
 
 // Create a pool of complex numbers to use in 
                    the algorithm
 private Complex fZ0 = new Complex (0.0, 0.0);
 private Complex fZ2 = new Complex (0.0, 0.0);
 private Complex fZ3 = new Complex (0.0, 0.0);
 
 /**
 *
 *  Create fractal patterns 
                    with the Julia set via
 *  Newton's method algorithm.
 *  Modify the pixels of 
                    a BufferedImage object and then
 *  draw the image with the 
                    given graphics context.
 *
 *  @param g graphics context
 *  @param frame_width display 
                    area width in pixels.
 *  @param frame_height display 
                    area height in pixels.
 *  @param frame_start_x 
                    horizontal point on display where
 *    drawing starts 
                    in pixel number.
 *  @param frame_start_y 
                    vertical point on display where
 *    drawing starts 
                    in pixel number.
 *  @param x_scale 2 dimensional 
                    array holding lower and
 *    upper values 
                    of the function input scale range.
 *  @param y_scale 2 dimensional 
                    array holding lower and
 *    upper values 
                    of the function output scale range.
 **/
 public void draw (Graphics g,
 int frame_start_x, int frame_start_y,
 int frame_width, int frame_height,
 double [] x_scale, double [] y_scale) {
 
 // Check if ready to draw the line
 if (fParameters == null) return;
 
 int y_max_index = y_scale.length - 
                    1;
 
 // Create an image on which to create 
                    the plot.
 // Size the image to fit within the 
                    frame
 int img_width  = frame_width  - 
                    1;
 int img_height = frame_height - 1;
 int numPixels = img_width * img_height;
 int [] pixels = new int [numPixels];
 
 // Get conversion factors from data 
                    scale to frame pixels
 double x_scale_factor = fParameters[0]/frame_width;
 double y_scale_factor = fParameters[1]/frame_height;
 
 // Create our complex variable for 
                    the algorithm.
 Complex z  = new Complex 
                    (0.0,0.0);
 
 // Coordinates in pixel scale
 int row = 0;
 int col = 0;
 int ipx = 0;
 
 // Outer loop steps through the c 
                    value along the horizontal axis.
 for (row = 0; row < img_height; row++) 
                    {
 // Change 
                    from pixel scale to the data scale
 double y_beg 
                    = y_scale[y_max_index] - row * y_scale_factor;
 
 for (col = 
                    0; col < img_width; col++) {
 ipx 
                    = col + row * img_width; // pixel pointer
 double 
                    x_beg = x_scale[0] + col * x_scale_factor;
 
 // 
                    Create the z for this point on the complex plane
 z.real 
                    = x_beg; z.img = y_beg; // Set the starting value.
 
 int 
                    iter   = 0;
 
 // 
                    Iterate the function:
 //   
                    z = z*z*z - 1
 do 
                    {
 // 
                    Use the pool complex objects to hold intermediate values
 fZ0.real 
                    = z.real; fZ0.img = z.img; // save z in fZ0
 z.multiply 
                    (z);  // z = z * z
 fZ2.real 
                    = z.real; fZ2.img = z.img; // save z*z in fZ2
 z.multiply 
                    (fZ0);// z = z * z * z
 fZ3.real 
                    = z.real; fZ3.img = z.img; // save z*z*z in fZ3
 
 // 
                    Now comute the iteration formula from Newton's method.
 //     
                    (z^3 -1.0)/(3.0 * z^2)
 fZ3.subtract 
                    (Z_ONE); // fZ3 = z*z*z - 1
 fZ2.multiply 
                    (Z_THREE); // fZ2 = 3.0 * z*z
 z.real 
                    = fZ3.real; z.img = fZ3.img;
 z.divide 
                    (fZ2); // z = (z^3 - 1.0)/(3.0 * z^2)
 
 ++iter;
 } 
                    while (iter < MAX_ITERATIONS && (!z.equals (fZ0)) );
 
 // 
                    Set color proportional to the number of interations.
 int 
                    colorComp = 20 * (iter%10);
 
 if 
                    (z.real > 0.0) { // root = 1
 pixels[ipx] 
                    =
 (colorComp 
                    << 16) | (colorComp << 8 ) | 0xFF;
 } 
                    else
 if 
                    (z.img > 0.0) { // root ~= -0.5 + .9i
 pixels[ipx] 
                    =
 (colorComp 
                    << 16) | (0xFF << 8 ) | colorComp;
 } 
                    else { // root ~= -0.5 - 0.9i
 pixels[ipx] 
                    =
 (0xFF 
                    << 16) | (colorComp << 8 ) | colorComp;
 }
 }
 }
 
 // Create a BufferedIamge of the RGB 
                    type.
 BufferedImage buf_img =
 new BufferedImage (img_width, 
                    img_height, BufferedImage.TYPE_INT_RGB);
 
 // Pass the image the pixel array.
 buf_img.setRGB (0,0,img_width,img_height,pixels,0,img_width);
 
 g.drawImage (buf_img, frame_start_x+1, 
                    frame_start_y+1, null);
 
 } // draw
 
 } // class DrawJuliaSetNewtonImg
 
 
   
 |   
                  | import 
                    java.awt.*; import java.awt.image.*;
 
 /**
 * Create a fractal pattern with the Mandlebrot 
                    method on
 * the pixels of a BufferedImage. Then draw this 
                    image.
 * Follows the algorithm given in "Java Number 
                    Cruncher"
 * by R. Mak for solving f(z) = z^3 -1 with Newton's
 * algorithm.
 *
 * Use a BufferedImage to create the plot.
 **/
 public class DrawMandlebrotImg extends DrawFunction
 {
 private static final int MAX_ITERATIONS   
                    = 32;
 private static final int ESCAPE_MAGNITUDE =  2;
 
 // Create two complex constants needed in the 
                    algorthm.
 private static final Complex Z_ONE   
                    = new Complex (1,0);
 private static final Complex Z_THREE = new Complex 
                    (3,0);
 
 // Create a pool of complex numbers to use in 
                    the algorithm
 private Complex fZ0 = new Complex (0.0, 0.0);
 private Complex fZ2 = new Complex (0.0, 0.0);
 private Complex fZ3 = new Complex (0.0, 0.0);
 
 /**
 *
 *  Create fractal patterns 
                    with the Mandlebrot algorithm.
 *  Modify the pixels of 
                    a BufferedImage object and then
 *  draw the image with the 
                    given graphics context.
 *
 *  @param g graphics context
 *  @param frame_width display 
                    area width in pixels.
 *  @param frame_height display 
                    area height in pixels.
 *  @param frame_start_x 
                    horizontal point on display where
 *    drawing starts 
                    in pixel number.
 *  @param frame_start_y 
                    vertical point on display where
 *    drawing starts 
                    in pixel number.
 *  @param x_scale 2 dimensional 
                    array holding lower and
 *    upper values 
                    of the function input scale range.
 *  @param y_scale 2 dimensional 
                    array holding lower and
 *    upper values 
                    of the function output scale range.
 **/
 public void draw (Graphics g,
 int frame_start_x, int frame_start_y,
 int frame_width, int frame_height,
 double [] x_scale, double [] y_scale) {
 
 // Check if ready to draw
 if (fParameters == null) return;
 
 // Create an image on which to create 
                    the plot
 // Size the image to fit within the 
                    frame
 int img_width  = frame_width  - 
                    1;
 int img_height = frame_height - 1;
 int numPixels = img_width * img_height;
 int [] pixels = new int [numPixels];
 
 int y_max_index = y_scale.length - 
                    1;
 
 // Get conversion factors from data 
                    scale to frame pixels
 double x_scale_factor = fParameters[0]/frame_width;
 double y_scale_factor = fParameters[1]/frame_height;
 
 // Create our complex variable for 
                    the algorithm.
 Complex z  = new Complex 
                    (0.0,0.0);
 Complex c  = new Complex 
                    (0.0,0.0);
 
 // Coordinates in pixel scale
 int row = 0;
 int col = 0;
 int ipx = 0;
 
 // Outer loop steps through the c 
                    value along the horizontal axis.
 for (row = 0; row < img_height; row++) 
                    {
 // Change 
                    from pixel scale to the data scale
 double y_beg 
                    = y_scale[y_max_index] - row * y_scale_factor;
 
 for (col = 
                    0; col < img_width; col++) {
 ipx 
                    = col + row * img_width; // pixel pointer
 double 
                    x_beg = x_scale[0] + col * x_scale_factor;
 
 // 
                    Create the c for this point on the complex plane
 c.real 
                    = x_beg; c.img = y_beg; // Set the complex constant
 z.real 
                    = 0.0;   z.img = 0.0;   // Initialize 
                    z to 0 + 0i.
 
 boolean 
                    escaped = false;
 int 
                    iter   = 0;
 double 
                    x   = x_beg;
 double 
                    y   = y_beg;
 double 
                    mag = 0.0;
 
 // 
                    Iterate the function:
 //   
                    z = z*z + c
 do 
                    {
 z.multiply 
                    (z);
 z.add 
                    (c);
 mag 
                    = z.modulus ();
 escaped 
                    = mag > ESCAPE_MAGNITUDE;
 ++iter;
 } 
                    while (iter < MAX_ITERATIONS && (!escaped));
 
 // 
                    If escaped, then set color to a shade of gray
 // 
                    proportional to the number of interations. The
 // 
                    more iterations, the darker
 if 
                    (escaped) {
 int 
                    gray = 0xFF - (0xFF*iter)/MAX_ITERATIONS;
 gray 
                    = Math.min (gray, 240);
 pixels[ipx] 
                    = (gray << 16) | (gray << 8 ) | gray;
 } 
                    else {
 
 // 
                    Did not escape so relate the color instead to the
 // 
                    final magnitude of z.
 
 int 
                    i = ((int)(100*mag)) / ESCAPE_MAGNITUDE + 1;
 int 
                    red = (100*i) & 0xFF;
 int 
                    grn = (150*i) & 0xFF;
 int 
                    blu = (200*i) & 0xFF;
 
 pixels[ipx] 
                    = (red << 16) | (grn << 8 ) | blu;
 }
 }
 }
 // Create a BufferedIamge of the RGB 
                    type.
 BufferedImage buf_img =
 new BufferedImage (img_width, 
                    img_height, BufferedImage.TYPE_INT_RGB);
 
 // Pass the image the pixel array.
 buf_img.setRGB (0,0,img_width,img_height,pixels,0,img_width);
 
 g.drawImage (buf_img, frame_start_x+1, 
                    frame_start_y+1, null);
 
 } // draw
 
 } // class DrawMandlebrotImg
 
 
   
 |    References & 
                Web Resources   Most recent update: June 24, 2005 |