11
\$\begingroup\$

The following is the program 3.2.6. from the book Computer Science An Interdisciplinary Approach by Sedgewick & Wayne:

// This data type is the basis for writing Java programs that manipulate complex numbers.    
public class Complex
{
    private final double re;
    private final double im;

    public Complex(double real, double imag)
    { re = real; im = imag; }
    public double re() 
    { return re; }
    public double im()
    { return im; }
    public double abs()
    { return Math.sqrt(re*re + im*im); }
    public Complex plus(Complex b)
    {
        double real = re + b.re;
        double imag = im + b.im;
        return new Complex(real, imag);
    }
    public Complex times(Complex b)
    {
        double real = re*b.re - im*b.im;
        double imag = re*b.im + im*b.re;
        return new Complex(real, imag);
    }
    public String toString()
    {
        return re + " + " + im + "i";
    }
    public static void main(String[] args)
    {
        Complex z0 = new Complex(1.0, 1.0);
        Complex z = z0;
        z = z.times(z).plus(z0);
        z = z.times(z).plus(z0);
        System.out.println(z);
    }
}

The next section in the book discusses the creation of Mandelbrot set in black-and-white. But before studying the program written by the authors of the book I tried to implement my own program to draw the Mandelbrot set in color.

Here is my program:

import java.awt.Color;

public class MandelbrotSet 
{
    public static int checkDegreeOfDivergence(Complex c, int degree)
    {
        Complex nextRecurrence = c;
        for (int i = 0; i < degree; i++)
        {
            if (nextRecurrence.abs() >= 2) return i;
            nextRecurrence = nextRecurrence.times(nextRecurrence).plus(c);
        }
        return degree;
    }
    public static double randomize(double left, double right)
    {
        return left + Math.random()*(right-left);
    } 
    public static Color[] createRandomColors(int degree)
    {
        Color[] colors = new Color[degree+1];
        colors[degree] = new Color(0,0,0);
        double r = Math.random();
        int red = 0, green = 0, blue = 0;
        if (r < 1.0/3.0) 
        {
            for (int i = 0; i < degree; i++)
            {
                red = 255;
                green = (int) randomize(0,255);
                blue = (int) randomize(0,255);
                colors[i] = new Color(red,green,blue);
            }
        }
        else if (r < 2.0/3.0) 
        {
            for (int i = 0; i < degree; i++)
            {
                red = (int) randomize(0,255);
                green = 255;
                blue = (int) randomize(0,255);
                colors[i] = new Color(red,green,blue);
            }
        }
        else if (r < 3.0/3.0) 
        {
            for (int i = 0; i < degree; i++)
            {
                red = (int) randomize(0,255);
                green = (int) randomize(0,255);
                blue = 255;
                colors[i] = new Color(red,green,blue);
            }
        }
        return colors;
    }
    public static void main(String[] args)
    {
        int width = Integer.parseInt(args[0]);
        int height = Integer.parseInt(args[1]);
        int contrast = Integer.parseInt(args[2]);
        double x = Double.parseDouble(args[3]);
        double y = Double.parseDouble(args[4]);
        double zoom = Double.parseDouble(args[5]);
        Picture mandelbrotSet = new Picture(width,height);
        Color[] colors = createRandomColors(contrast);
        for (int j = 0; j < width; j++)
        {
            for (int i = 0; i < height; i++)
            {
                double realPart = x + zoom*j/width;
                double imaginaryPart = y + zoom*i/height;
                Complex c = new Complex(realPart,imaginaryPart);
                int degreeOfDivergence = checkDegreeOfDivergence(c, contrast);
                Color color = colors[degreeOfDivergence];
                mandelbrotSet.set(j,i,color);       
            }
        }
        mandelbrotSet.show();
    }
}

Picture is a simple API written by the authors of the book. I checked my program and it works. Here are a few instances of it:

Input: 3840 2160 255 -0.1015 0.833 0.01

Output:

enter image description here

Input 3840 2160 255 -0.2404 0.8354 0.001

Output:

enter image description here

Input: 3840 2160 255 0.1015 -0.633 0.01

Output:

enter image description here

One thing to note: The above pictures are not in the original resolution. Due to size restriction of uploads I took screenshots of the original images. I did not decrease the resolution of the above pictures directly from the command-line because I wanted them to look prettier.

One other thing to note: Since blue is my favorite color, they are intentionally in the blue spectrum.

Is there any way that I can improve my program?

Thanks for your attention.

New edit:

I added the following method to the Complex class:

public Complex conjugate() 
{
    return new Complex(re, -1.0*im);
}

and the following method to the MandelbrotSet class:

public static int checkDegreeOfDivergenceForMandelbar(Complex c, int degree)
{
    Complex nextRecurrence = c;
    for (int i = 0; i < degree; i++)
    {
        if (nextRecurrence.abs() >= 2) return i;
        nextRecurrence = (nextRecurrence.conjugate()).times(nextRecurrence.conjugate()).plus(c);
    }
    return degree;
}

Here is one instance of this Mandelbar set:

Input: 3840 2160 255 -1.5 -1.5 3

Output:

enter image description here

Newer edit:

I found an ASTONISHING color palette from the book site and applied it as follows (within the createRandomColors method):

    for (int i = 0; i < degree; i++)
    {
        red = 13*(256-i) % 256;
        green = 7*(256-i) % 256;
        blue = 11*(256-i) % 256;
        colors[i] = new Color(red,green,blue);
    }

Here is one of the above results with this new color palette:

enter image description here

\$\endgroup\$
10
  • 2
    \$\begingroup\$ Unfortunately, I've forgotten too much Java to be able to comment on anything here, except, playing around with coloring is a lot of fun. You're doing it quite different than I normally do. I usually create a "color function" that accepts the current (r)eal and (i)maginary values, and the (n)umber of iterations that it failed at, multiply each by multipliers passed in, then wrap the result so it's in the range 0-255. You can get great coloring from that. \$\endgroup\$ Commented Sep 12, 2020 at 13:46
  • \$\begingroup\$ @Carcigenicate Thank you very much. I was actually thinking about the way in which you did it. :) \$\endgroup\$ Commented Sep 12, 2020 at 18:33
  • 1
    \$\begingroup\$ Np. My PHP port might be easier to read; Clojure is a bit obscure. And unfortunately, this technique is obviously limited to relatively simple linear equations, but it still leads to a ton of different possible designs. I spent a solid week playing around with coloring. I have several gigabytes of pictures produced from it. Good times. \$\endgroup\$ Commented Sep 12, 2020 at 18:47
  • \$\begingroup\$ Wow! I might do it as well. \$\endgroup\$ Commented Sep 12, 2020 at 19:02
  • \$\begingroup\$ @Carcigenicate Check out the new color palette. \$\endgroup\$ Commented Sep 12, 2020 at 19:26

1 Answer 1

1
\$\begingroup\$

After experimenting with my program for two days, I found that the use of degree within the methods checkDegreeOfDivergence and createRandomColors does not increase the quality of the pictures and so I removed it.

Also to increase the variety of colors I changed the following code

public static Color[] createRandomColors(int degree)
{
    Color[] colors = new Color[degree+1];
    colors[degree] = new Color(0,0,0);
    double r = Math.random();
    int red = 0, green = 0, blue = 0;
    for (int i = 0; i < degree; i++)
    {
        red = 13*(256-i) % 256;
        green = 7*(256-i) % 256;
        blue = 11*(256-i) % 256;
        colors[i] = new Color(red,green,blue);
    }
    return colors;
}

into

public static Color[] createRandomColors()
{
    Color[] colors = new Color[256];
    double r = Math.random();
    int red = 0, green = 0, blue = 0;
    if (r < 1.0/6.0) 
    {
        for (int i = 0; i < 256; i++)
        {
            red = 13*(256-i) % 256;
            green = 7*(256-i) % 256;
            blue = 11*(256-i) % 256;
            colors[i] = new Color(red,green,blue);
        }
    }
    else if (r < 2.0/6.0) 
    {
        for (int i = 0; i < 256; i++)
        {
            red = 13*(256-i) % 256;
            green = 7*(256-i) % 256;
            blue = 11*(256-i) % 256;
            colors[i] = new Color(red,blue,green);
        }
    }
    else if (r < 3.0/6.0) 
    {
        for (int i = 0; i < 256; i++)
        {
            red = 13*(256-i) % 256;
            green = 7*(256-i) % 256;
            blue = 11*(256-i) % 256;
            colors[i] = new Color(green,red,blue);
        }
    }
    else if (r < 4.0/6.0) 
    {
        for (int i = 0; i < 256; i++)
        {
            red = 13*(256-i) % 256;
            green = 7*(256-i) % 256;
            blue = 11*(256-i) % 256;
            colors[i] = new Color(green,blue,red);
        }
    }
    else if (r < 5.0/6.0) 
    {
        for (int i = 0; i < 256; i++)
        {
            red = 13*(256-i) % 256;
            green = 7*(256-i) % 256;
            blue = 11*(256-i) % 256;
            colors[i] = new Color(blue,red,green);
        }
    }
    else if (r < 6.0/6.0) 
    {
        for (int i = 0; i < 256; i++)
        {
            red = 13*(256-i) % 256;
            green = 7*(256-i) % 256;
            blue = 11*(256-i) % 256;
            colors[i] = new Color(blue,green,red);
        }
    }
    return colors;
}

and so there is no need for randomize anymore and the whole program changes as follows

import java.awt.Color;

public class MandelbrotSet 
{
    public static int checkDegreeOfDivergence(Complex c)
    {
        Complex nextRecurrence = c;
        for (int i = 0; i < 255; i++)
        {
            if (nextRecurrence.abs() >= 2) return i;
            nextRecurrence = nextRecurrence.times(nextRecurrence).plus(c);
        }
        return 255;
    }
    public static int checkDegreeOfDivergenceForMandelblar(Complex c)
    {
        Complex nextRecurrence = c;
        for (int i = 0; i < 255; i++)
        {
            if (nextRecurrence.abs() >= 2) return i;
            nextRecurrence = (nextRecurrence.conjugate()).times(nextRecurrence.conjugate()).plus(c);
        }
        return 255;
    }
    public static Color[] createRandomColors()
    {
        Color[] colors = new Color[256];
        double r = Math.random();
        int red = 0, green = 0, blue = 0;
        if (r < 1.0/6.0) 
        {
            for (int i = 0; i < 256; i++)
            {
                red = 13*(256-i) % 256;
                green = 7*(256-i) % 256;
                blue = 11*(256-i) % 256;
                colors[i] = new Color(red,green,blue);
            }
        }
        else if (r < 2.0/6.0) 
        {
            for (int i = 0; i < 256; i++)
            {
                red = 13*(256-i) % 256;
                green = 7*(256-i) % 256;
                blue = 11*(256-i) % 256;
                colors[i] = new Color(red,blue,green);
            }
        }
        else if (r < 3.0/6.0) 
        {
            for (int i = 0; i < 256; i++)
            {
                red = 13*(256-i) % 256;
                green = 7*(256-i) % 256;
                blue = 11*(256-i) % 256;
                colors[i] = new Color(green,red,blue);
            }
        }
        else if (r < 4.0/6.0) 
        {
            for (int i = 0; i < 256; i++)
            {
                red = 13*(256-i) % 256;
                green = 7*(256-i) % 256;
                blue = 11*(256-i) % 256;
                colors[i] = new Color(green,blue,red);
            }
        }
        else if (r < 5.0/6.0) 
        {
            for (int i = 0; i < 256; i++)
            {
                red = 13*(256-i) % 256;
                green = 7*(256-i) % 256;
                blue = 11*(256-i) % 256;
                colors[i] = new Color(blue,red,green);
            }
        }
        else if (r < 6.0/6.0) 
        {
            for (int i = 0; i < 256; i++)
            {
                red = 13*(256-i) % 256;
                green = 7*(256-i) % 256;
                blue = 11*(256-i) % 256;
                colors[i] = new Color(blue,green,red);
            }
        }
        return colors;
    }
    public static void main(String[] args)
    {
        int width = Integer.parseInt(args[0]);
        int height = Integer.parseInt(args[1]);
        double x = Double.parseDouble(args[2]);
        double y = Double.parseDouble(args[3]);
        double zoom = Double.parseDouble(args[4]);
        Picture mandelbrotSet = new Picture(width,height);
        Color[] colors = createRandomColors();
        for (int j = 0; j < width; j++)
        {
            for (int i = 0; i < height; i++)
            {
                double realPart = x + zoom*j/width;
                double imaginaryPart = y + zoom*i/height;
                Complex c = new Complex(realPart,imaginaryPart);
                int degreeOfDivergence = checkDegreeOfDivergence(c);
                Color color = colors[degreeOfDivergence];
                mandelbrotSet.set(j,i,color);       
            }
        }
        mandelbrotSet.show();
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.