Skip to content

Instantly share code, notes, and snippets.

@RustyKnight
Created July 20, 2022 00:59
Show Gist options
  • Save RustyKnight/b7efc142a543f016e335b11b9d679f14 to your computer and use it in GitHub Desktop.
Save RustyKnight/b7efc142a543f016e335b11b9d679f14 to your computer and use it in GitHub Desktop.
An example of using threads to generate a fractal
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
public class ThreadedFractal {
public static void main(String[] args) throws InterruptedException {
int k = 19000;
BufferedImage image = new BufferedImage(k, k, BufferedImage.TYPE_INT_RGB);
int threadWorking = 0;
int nbProc = Runtime.getRuntime().availableProcessors();
ExecutorService service = Executors.newFixedThreadPool(nbProc);
List<FractalCallable> tasks = new ArrayList<>(nbProc);
for (int i = 0; i < nbProc; i++) {
//new MandelbrotImage(k*k*i/nbProc,k*k*(i+1)/nbProc,k);
int a = (int) ((k * k * (long) i) / nbProc);
int b = (int) ((k * k * ((long) i + 1)) / nbProc);
tasks.add(new FractalCallable(
i,
image,
a,
b,
k
));
}
System.out.println("Now building..." + tasks.size());
List<Future<Void>> results = service.invokeAll(tasks);
System.out.println("Done processing" + results.size());
try {
for (Future<Void> result : results) {
result.get();
}
System.out.println("Writing images");
ImageIO.write(image, "png", new File("Test.png"));
} catch (ExecutionException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
service.shutdownNow();
System.out.println("All done");
}
public static class FractalCallable implements Callable<Void> {
private int count;
private BufferedImage image;
private int a, b, k;
public FractalCallable(int count, BufferedImage image, int a, int b, int k) {
this.count = count;
this.image = image;
this.a = a;
this.b = b;
this.k = k;
}
@Override
public Void call() throws Exception {
int x = 0;
int y = 0;
try {
for (int u = a; u < b; u++) {
x = u % k;
y = u / k;
image.setRGB(
x,
y,
function(((u % k) / (k / 2.0)) - 1.5,
(u / (k * k / 2.0)) - 1,
1));
}
System.out.println("Completed " + count);
} catch (Exception exp) {
System.out.println(count + "Failed to write to " + x + "x" + y);
System.out.println("Started " + count + "; a = " + a + "; b = " + b + "; k = " + k);
throw exp;
}
return null;
}
public int function(double real, double imag, int accuracy) {
int max;
double p = (real - 0.25) * (real - 0.25) + imag * imag;
if ((real + 1) * (real + 1) + imag * imag < 1d / 16d || real < Math.sqrt(p) - 2 * p + 0.25) {
max = 0;
} else {
double a = 0, b = 0, temp;
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))).getRGB();
}
}
}
@RustyKnight
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment