This comment was posted to reddit on Sep 21, 2017 at 2:20 pm and was deleted within 11 minutes.

The code is a bit complicated because I actually multi-threaded the generator. I also programmed it in Java, so it is fairly verbose. However, I don't mind sharing the important bits.
First, I defined a ComplexNumber class.
public class ComplexNumber {
/*
* Complex number format: a + bi
* i = sqrt(-1)
*/
private double a, b;
public ComplexNumber(double a, double b) {
setNumber(a, b);
}
public void setNumber(double a, double b){
this.a = a;
this.b = b;
}
public void setA(double a){
this.a = a;
}
public void setB(double b){
this.b = b;
}
public double getA(){
return a;
}
public double getB(){
return b;
}
public static ComplexNumber add(ComplexNumber num1, ComplexNumber num2){
return new ComplexNumber((num1.getA() + num2.getA()), (num1.getB() + num2.getB()));
}
public static ComplexNumber subtract(ComplexNumber num1, ComplexNumber num2){
return new ComplexNumber((num1.getA() - num2.getA()), (num1.getB() - num2.getB()));
}
public static ComplexNumber multiply(ComplexNumber num1, ComplexNumber num2){
return new ComplexNumber((num1.getA()*num2.getA() - num1.getB()*num2.getB()), (num1.getB()*num2.getA() + num1.getA()*num2.getB()));
}
public static ComplexNumber divide(ComplexNumber num1, ComplexNumber num2){
double div = (num2.getA() * num2.getA()) + (num2.getB() * num2.getB());
ComplexNumber multi = multiply(num1, new ComplexNumber(num2.getA(), num2.getB() * -1));
ComplexNumber o = new ComplexNumber(multi.getA()/div, multi.getB()/div);
return o;
}
public static ComplexNumber pow(ComplexNumber num, int i){
if(i == 1){
return num;
}
else{
return multiply(num, pow(num, i - 1));
}
}
public static int stepsToBreakMandelbrotSet(ComplexNumber input, int cap){
ComplexNumber iterate = new ComplexNumber(0, 0);
for(int x = 0; x < cap; x++){
iterate = add(multiply(iterate, iterate), input);
if(Math.sqrt(iterate.getA() * iterate.getA() + iterate.getB() * iterate.getB()) >= 2){
return x;
}
}
return cap;
}
}
This class includes static functions for performing operations on complex numbers and a function that finds the number of iterations it takes for a complex number to escape the Mandlebrot set. If the input number is found to "shoot away" from the mandlebrot set after a certain number of iterations (a varible I named "cap") it will just return cap. After that, I used another class to create a color array, and assign an appropriate color to that pixel depending on its position in the plot.
import java.awt.Color;
public class MandelbrotToColorArray {
private double xShift = 0;
private double yShift = 0;
private double zoom = 1;
private int capFactor = 25;
private Color[][] c;
private int width = 7680;
private int height = 4320;
public void configMandelbrotInfo(double xShift, double yShift, double zoom, Color[][] c){
this.xShift = xShift;
this.yShift = yShift;
this.zoom = zoom;
this.c = c;
}
public void configPictureInfo(int width, int height, int capFactor){
this.width = width;
this.height = height;
this.capFactor = capFactor;
}
public void paintMandelbrot(int x1, int y1, int x2, int y2){
int cap = capFactor;
double pixelDeltaY = 4/((double)height * zoom);
for(int x = x1; x < x2 + x1; x++){
for(int y = y1; y < y2 + y1; y++){
ComplexNumber toTest = new ComplexNumber((xShift + x*pixelDeltaY - pixelDeltaY*(0.5 * width)), (yShift + y*pixelDeltaY - pixelDeltaY*(0.5 * height)));
int capTest = ComplexNumber.stepsToBreakMandelbrotSet(toTest, cap);
if(capTest == cap){
c[x][y] = new Color(0, 0, 0);
}
else{
final int[] targetColor = {255, 0, 0};
c[x][y] = new Color((int) (targetColor[0] * ((double) capTest/(double) cap)),
(int) (targetColor[1] * ((double) capTest/(double) cap)),
(int) (targetColor[2] * ((double) capTest/(double) cap)));
}
}
}
}
}
After selecting a reigon of the Mandlebrot set to render, it takes each pixel and finds its respected location on the minaginary plane, and runs it through stepsToBreakMandelbrotSet(toTest, cap). If the integer returned is equal to cap, then that complex number is assumed to be in the Mandlebrot set.
Color assignments *usually* work by haveing pixels inside the Mandlebrot set be rbg(0, 0, 0), or black, and have Pixels extremely close to the set be some target color, usually red. However, I did play with other methods of assigning colors to pixels, so that isn't quite the full story.
Beyond those two classes, all there is left is another class that manages multithreading, and saves the resulting color array as a PNG.