
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.
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;
}
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:
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;
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;
}
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();
}
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;
}
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();
}
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);
});
}
javac JuliaFractal.java
java JuliaFractal
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!