Tutorial - how to code this interactive Julia fractal in Java:

Introduction

This tutorial will guide you through creating an interactive Julia fractal visualizer in Java AWT, with the ability to zoom by clicking on the image.

Download the full code here: JuliaFractal.java or follow the steps below.

Step 1: Basic setup

Start by creating a class that extends JPanel and implements MouseListener:

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;

public class JuliaFractal extends JPanel implements MouseListener {
    private static final int WIDTH = 800;
    private static final int HEIGHT = 800;
    private static final int MAX_ITER = 256;
    
    private BufferedImage img;
}

Step 2: Defining Julia fractal constants

The Julia fractal is defined by the complex constant c = cRe + cIm*i:

private double cRe = -0.7;
private double cIm = 0.27015;

Different values of c create completely different fractals. Try these values:

Step 3: Defining the view window

These variables determine which part of the complex plane is visible:

private double minRe = -1.5;
private double maxRe = 1.5;
private double minIm = -1.5;
private double maxIm = 1.5;

Step 4: Julia fractal algorithm

The main function computes whether a complex point belongs to the Julia set:

private int julia(double zRe, double zIm) {
    int n = 0;
    while (n < MAX_ITER) {
        double zRe2 = zRe * zRe;
        double zIm2 = zIm * zIm;
        
        // If the point escapes to infinity
        if (zRe2 + zIm2 > 4.0) break;
        
        // Formula: z = z² + c
        double newRe = zRe2 - zIm2 + cRe;
        double newIm = 2 * zRe * zIm + cIm;
        
        zRe = newRe;
        zIm = newIm;
        n++;
    }
    return n;
}
How it works:

Step 5: Rendering the fractal

This function iterates over every pixel of the image:

private void renderFractal() {
    double reRange = maxRe - minRe;
    double imRange = maxIm - minIm;
    
    for (int y = 0; y < HEIGHT; y++) {
        for (int x = 0; x < WIDTH; x++) {
            // Convert pixel coordinates to complex coordinates
            double re = minRe + (x * reRange) / WIDTH;
            double im = minIm + (y * imRange) / HEIGHT;
            
            int iter = julia(re, im);
            int color = getColor(iter);
            img.setRGB(x, y, color);
        }
    }
    repaint();
}

Step 6: Coloring the fractal

This function maps the iteration count to a color:

private int getColor(int iter) {
    if (iter == MAX_ITER) return 0x000000; // Black for the set
    
    double t = (double) iter / MAX_ITER;
    
    // Bernstein polynomials for smooth gradients
    int r = (int) (9 * (1 - t) * t * t * t * 255);
    int g = (int) (15 * (1 - t) * (1 - t) * t * t * 255);
    int b = (int) (8.5 * (1 - t) * (1 - t) * (1 - t) * t * 255);
    
    return (r << 16) | (g << 8) | b;
}

Step 7: Implementing interactive zooming

When the user clicks, we recalculate the view window:

@Override
public void mouseClicked(MouseEvent e) {
    double reRange = maxRe - minRe;
    double imRange = maxIm - minIm;
    
    // Convert click to complex coordinates
    double clickRe = minRe + (e.getX() * reRange) / WIDTH;
    double clickIm = minIm + (e.getY() * imRange) / HEIGHT;
    
    // Zoom by 50%
    double zoomFactor = 0.5;
    double newReRange = reRange * zoomFactor;
    double newImRange = imRange * zoomFactor;
    
    // Center on the clicked point
    minRe = clickRe - newReRange / 2;
    maxRe = clickRe + newReRange / 2;
    minIm = clickIm - newImRange / 2;
    maxIm = clickIm + newImRange / 2;
    
    renderFractal();
}

Step 8: Creating the graphical interface

public JuliaFractal() {
    setPreferredSize(new Dimension(WIDTH, HEIGHT));
    addMouseListener(this);
    img = new BufferedImage(WIDTH, HEIGHT, BufferedImage.TYPE_INT_RGB);
    renderFractal();
}

@Override
public void paintComponent(Graphics g) {
    super.paintComponent(g);
    g.drawImage(img, 0, 0, null);
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(() -> {
        JFrame frame = new JFrame("Julia Fractal - Click to zoom");
        JuliaFractal fractal = new JuliaFractal();
        frame.add(fractal);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    });
}

Possible improvements

  1. Add a reset button to return to the initial view
  2. Allow zooming out with the right mouse button
  3. Add a loading indicator for long computations
  4. Multithreading to speed up rendering
  5. Selection of different c values to explore other fractals
  6. Saving images to capture your discoveries

Compile and run

javac JuliaFractal.java
java JuliaFractal

Summary

You now have a working Julia fractal visualizer! Julia fractals reveal infinitely complex and self-similar structures. Each zoom uncovers new fascinating details. Have fun exploring!