Buddhabrot Applet
By Aaron Davidson

This applet plots a version of the Mandelbrot Set known as the Buddhabrot. It is quite CPU intensive and takes a while to render into something nice looking. For a large high-quality rendering, here is a large image I rendered overnight on a distributed cluster of computers.

Source Code - Buddhabrot.java

package ca.spaz.fractal;

import java.awt.*;
import java.awt.image.BufferedImage;

import javax.swing.*;

/**
 * Created on Feb 8, 2004
 
 * Source code given to public domain. Enjoy.
 
 @author Aaron Davidson <aaron@spaz.ca> 
 */
public class BuddhaBrot extends JComponent {
   private static final int RED_DWELL = 8000;
   private static final int GREEN_DWELL = 2000;
   private static final int BLUE_DWELL = 500;
   
   private boolean stop = false;
   
   // exposure counters for each pixel & color
   private int[][] exposureBlue;
   private int[][] exposureRed;
   private int[][] exposureGreen;
   
   // max values for normalization
   private int maxexposureBlue;
   private int maxexposureRed; 
   private int maxexposureGreen;   
   
   // number of actual exposures
   private int exposures = 0;
   
   // out image buffer for rendering
   private BufferedImage off;

   public BuddhaBrot(int w, int h) {
      exposureBlue = new int[w][h];
      exposureRed = new int[w][h];
      exposureGreen = new int[w][h];

      off = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
      
      Thread t = new Thread(new Runnable() {
         public void run() {
            renderLoop();
         }
      });
      t.start();
   }

   /**
    * We just keep adding samples and redrawing the screen. Forever.
    */
   public void renderLoop() {
      while (!stop) {
         refresh();
         plot(100000);
      }
   }

   public int getWidth() {
     return off.getWidth();  
   }

   public int getHeight() {
      return off.getHeight();
   }

   /**
    * Generates another round of sample exposures to add to the image
    @param samples number of samples to take
    */
   void plot(int samples) {
      double x, y;
      // iterate through some plots
      for (int n=0; n<samples; n++) {
         // Choose a random point in same range
         x = random(-2.0,1.0);
         y = random(-1.5,1.5);
         if (iterate(x, y, false, BLUE_DWELL, exposureBlue)) {
            iterate(x, y, true, BLUE_DWELL, exposureBlue);
            exposures++;
         }
         if (iterate(x, y, false, GREEN_DWELL, exposureGreen)) {
            iterate(x, y, true, GREEN_DWELL, exposureGreen);
            exposures++;
         }
         if (iterate(x, y, false, RED_DWELL, exposureRed)) {
            iterate(x, y, true, RED_DWELL, exposureRed);
            exposures++;
         }
      }
   }
   
   /**
    * Pick a random value between min and max.
    */
   final double random(double min, double max) {
      return min + (Math.random() * Math.abs(max - min));
   }

   /**
    * Test a single coordinate against a given dwell value.
    @param x0 random x coordinate
    @param y0 random y coordinate
    @param drawIt if true, we fill in values
    @param dwell the dwell (bailout) value
    @param expose exposure array to fill in results
    @return true if we escaped before bailout
    */
   private boolean iterate(double x0, double y0, boolean drawIt, int dwell, int[][] expose) {
      double x = 0;
      double y = 0;
      double xnew, ynew;
      int ix, iy;

      for (int i=0; i<dwell; i++) {
         xnew = x * x - y * y + x0;
         ynew = * x * y + y0;
         if (drawIt && (i > 3)) {
            ix = (int)(getHeight() (xnew + 2.03.0);
            iy = (int)(getWidth() (ynew + 1.53.0);
            if (ix >= && iy >= && ix < getHeight() && iy < getWidth()) {               
               expose[iy][ix]++; // rotate and expose point
            }
         }
         if ((xnew*xnew + ynew*ynew4) {            
            return true// escapes
         }
         x = xnew;
         y = ynew;
      }
      return false;  // does not escape
   }
      
   /**
    * Find the largest exposure values for normalization 
    */
   private void findMaxExposure() {
      maxexposureBlue = maxexposureRed = maxexposureGreen =0;
      for (int i=0;i<getHeight();i++) {
         for (int j=0;j<getWidth();j++) {
            maxexposureBlue = Math.max(maxexposureBlue,exposureBlue[j][i]);
            maxexposureRed = Math.max(maxexposureRed,exposureRed[j][i]);
            maxexposureGreen = Math.max(maxexposureGreen,exposureGreen[j][i]);
         }
      }
   }
   
   /**
    * Update screen bitmap with latest results
    */
   public synchronized void refresh() {
      findMaxExposure();
      for (int i=0;i<getHeight();i++) {
         for (int j=0;j<getWidth();j++) {
            double blue = exposureBlue[j][i(maxexposureBlue / 2.5);
            if (blue > 1)  {
               blue = 1;
            }
            double red = exposureRed[j][i(maxexposureRed / 2.5);
            if (red > 1)  {
               red = 1;
            }
            double green = exposureGreen[j][i(maxexposureGreen / 2.5);
            if (green > 1)  {
               green = 1;
            }            
            Color c = new Color((int)(red*255)(int)(green*255)(int)(blue*255));
            off.setRGB(j,i,c.getRGB());
         }
      }
      repaint()// trigger a repaint
   }

   /**
    * Override update method to prevent flicker
    */
   public void update(Graphics g) {
      repaint();
   }
   
   /**
    * Just blit our image buffer to the screen
    */
   public synchronized void paint(Graphics g) {
      g.drawImage(off, 00null);    
   }

}
Java2html