javaswingfractals

how to draw image pixel by piexel in swing


I recently created a program to explore Mandelbrot's fractal and after calculated the image I drew it but in a weird way. How can I paint it in clean way? The only way I found is to override the paint method and fill rectangle of 1 pixel (I know the function to get the color is horrible but it's to make a compact code even if it's useless).

import java.awt.Color;
import javax.swing.JFrame;
public class Mandelbrot{
    public static void main(String[] args) {
        var panel = new javax.swing.JComponent() {
            public void paint(java.awt.Graphics g) {
                for (int i = 0; i < 1000000; i++) {
                    g.setColor(function(((i % 1000) / 500.0)/zoom + x, (i / 500000.0) / zoom + y, 1));
                    g.fillRect(i % 1000, i / 1000, 1, 1);
                }
            }
        };
        panel.addMouseListener(new java.awt.event.MouseAdapter() {
            @Override
            public void mouseClicked(java.awt.event.MouseEvent e) {
                x += (e.getX() / 1000.0) / zoom;
                y += (e.getY() / 1000.0) / zoom;
                zoom = e.getButton() == 1 ? zoom * 2 : (zoom == 1 ? 1 : zoom / 2);
                panel.repaint();
                System.out.println("zoom : X" + zoom);
            }
        });
        panel.setBounds(0, 0, 1024, 1024);
        var frame = new JFrame("FRACTAL");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(1000, 1000);
        frame.add(panel);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
    private static double a, b, temp, x = -1.5, y = -1;
    private static int zoom = 1;
    public static Color function(double real, double imag, int accuracy) {
        a = 0; b = 0;
        int max= 1024 * accuracy;
        while(max > 0 && a*a + b*b < 4){
            temp = a;
            a = a*a - b*b + real;
            b = 2*temp*b + imag;
            max--;
        }
        max = (1024*accuracy - max) / accuracy;
        return max == 1024 ? Color.BLACK : new Color(max < 256 ? 255:(max < 512 ? 511 - max : 0), max < 256 ? max : (max < 768 ? 255 : 1023 - max), max < 512 ? 0 : (max < 768 ? max - 512 : 255));
    }
}

Solution

  • You can create a BufferedImage, edit it, and than add it to you frame inside a JLable, like this:

    JLabel lable = new JLabel(new ImageIcon(yourBufferedImage));
    frame.addLabel();
    

    This will prevent you from re-calculating your image every time you repaint it. To update the image, you should edit your BufferedImage and than update your label icon, like this:

    label.setIcon(new ImageIcon(yourBufferedImage));
    label.repaint();