E:\Src\java\netBeans\Mandelbrot\src\mandelbrot\Mandelbrot.java |
package mandelbrot;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
@author
public class Mandelbrot extends JPanel implements MouseListener, KeyListener, MouseWheelListener {
static int width = 800;
static int height = 600;
double centreX = 0;
double centreY = 0;
double dx = 4;
int max_iteration = 50;
int printScale = 5;
int mouse_X = 0;
int mouse_Y = 0;
boolean busy = false;
BufferedImage img = null;
JProgressBar progressBar;
int regOffset = 0;
public Mandelbrot(JFrame frame) {
addMouseListener(this);
frame.addKeyListener(this);
addMouseWheelListener(this);
progressBar = new JProgressBar(0, width);
progressBar.setValue(0);
progressBar.setStringPainted(true);
add(progressBar);
img = createMyImage(width, height, max_iteration, 1);
}
private void saveFile(BufferedImage img) {
Calendar now = Calendar.getInstance();
File outputfile = new File("c:\\temp\\MandelBrot " +
now.get(Calendar.YEAR) +
"." + now.get(Calendar.MONTH) +
"." + now.get(Calendar.DAY_OF_MONTH) +
" " + now.get(Calendar.HOUR_OF_DAY) +
"_" + now.get(Calendar.MINUTE) + ".png");
System.out.println("Start writing to file: " + outputfile.getAbsolutePath());
try {
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(outputfile));
ImageIO.write(img, "png", outputStream);
outputStream.close();
} catch (IOException ex) {
Logger.getLogger(Mandelbrot.class.getName()).log(Level.SEVERE, null, ex);
}
System.out.println(" created");
}
public void paint(Graphics g) {
if (img != null) {
g.drawImage(img, 0, 0, this);
}
}
private double getMinCx() {
return centreX - dx / 2.0;
}
private double getMaxCx() {
return centreX + dx / 2.0;
}
private double getMinCy() {
return centreY - dx / 2.0 * (double) height / (double) width;
}
private double getMaxCy() {
return centreY + dx / 2.0 * (double) height / (double) width;
}
private int getPixW(double p, int width, int height) {
return (int) (width * (p - getMinCx()) / (getMaxCx() - getMinCx()));
}
private int getPixH(double p, int width, int height) {
return (int) (height * (p - getMinCy()) / (getMaxCy() - getMinCy()));
}
private double getResolution(int width) {
return (getMaxCx() - getMinCx()) / width;
}
private BufferedImage createMyImage(int width, int height, int max_iteration, int zoom) {
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
double max_betrags_quadrat = 4;
double point_dx = getResolution(width);
progressBar.setMaximum(width);
for (int pix_x = 0; pix_x < width; pix_x++) {
progressBar.setValue(pix_x);
double cx = getMinCx() + pix_x * point_dx;
for (int pix_y = 0; pix_y < height; pix_y++) {
double cy = getMinCy() + pix_y * point_dx;
int iteration = punkt_iteration(cx, cy, max_betrags_quadrat, max_iteration);
int rgb = set_rgb(iteration, max_iteration);
bufferedImage.setRGB(pix_x, pix_y, rgb);
}
}
Graphics g = bufferedImage.getGraphics();
g.setColor(Color.WHITE);
g.setFont(new Font("TimesRoman", Font.PLAIN, 12 * zoom));
g.drawString("Z[n+1] = Z²[n] + c; Z[0]=0; c=complex; n=0,1,2,...; |Z[n]|>=2", 32 * zoom, 32 * zoom);
g.drawString("center: " + (getMinCx() + width / 2 * point_dx) + " " +
(-(getMinCy() + height / 2 * point_dx)) + "j", 32 * zoom, 55 * zoom);
int y = getPixH(0, width, height);
g.drawLine(0, y, width, y);
int x = getPixW(0, width, height);
g.drawLine(x, 0, x, height);
progressBar.setValue(width);
return bufferedImage;
}
private int get_rgb(int Wert) {
Wert = Wert * 4;
Wert = Wert % 254;
int Red, Green, Blue = 0;
int Phase = Wert / 51;
int Level = Wert % 51;
switch (Phase) {
case 0:
Red = 255;
Green = Level * 5;
Blue = 0;
break;
case 1:
Red = 255 - Level * 5;
Green = 255;
Blue = 0;
break;
case 2:
Red = 0;
Green = 255;
Blue = Level * 5;
break;
case 3:
Red = 0;
Green = 255 - Level * 5;
Blue = 255;
break;
case 4:
Red = Level * 5;
Green = 0;
Blue = 255;
break;
default:
Red = Green = Blue = 255;
}
return Red * 256 * 256 + Green * 256 + Blue;
}
private int set_rgb(int iteration, int max_iteration) {
if (iteration == max_iteration) {
return Color.BLACK.getRGB();
}
return get_rgb(regOffset + iteration);
}
private int punkt_iteration(double cx, double cy, double max_betrag_quadrat, int max_iter) {
double betrag_quadrat = 0;
int iter = 0;
double x = 0;
double y = 0;
while (betrag_quadrat <= max_betrag_quadrat && iter < max_iter) {
double xt = x * x - y * y + cx;
double yt = 2 * x * y + cy;
x = xt;
y = yt;
iter++;
betrag_quadrat = x * x + y * y;
}
return iter;
}
@Override
public void mouseClicked(MouseEvent e) {
if (!busy) {
busy = true;
mouse_X = e.getX();
mouse_Y = e.getY();
double zoom = 2;
switch (e.getModifiers()) {
case InputEvent.BUTTON1_MASK: {
new Thread(new Runnable() {
@Override
public void run() {
img = createMyImage(width, height, max_iteration, 1);
repaint();
busy = false;
}
}).start();
break;
}
case InputEvent.BUTTON2_MASK: {
zoom = 1.0;
mouse_X = width / 2;
mouse_Y = height / 2;
new Thread(new Runnable() {
@Override
public void run() {
saveFile(createMyImage(width * printScale, height * printScale, max_iteration, printScale));
busy = false;
}
}).start();
break;
}
case InputEvent.BUTTON3_MASK: {
zoom = 1 / zoom;
new Thread(new Runnable() {
@Override
public void run() {
img = createMyImage(width, height, max_iteration, 1);
repaint();
busy = false;
}
}).start();
break;
}
}
centreX = getMinCx() + (dx * (double) (mouse_X) / (double) width);
double dy = (getMaxCy() - getMinCy());
centreY = getMinCy() + (dy * (double) (mouse_Y) / (double) height);
dx = dx / zoom;
}
}
@Override
public void mousePressed(MouseEvent e) {
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
}
@Override
public void keyPressed(KeyEvent e) {
boolean repaint = true;
switch (e.getKeyChar()) {
case 'u':
max_iteration = max_iteration * 2;
break;
case 'd':
max_iteration = max_iteration / 2;
break;
default:
System.out.println("not supported: " + e.getKeyChar());
repaint = false;
}
if (!busy && repaint) {
busy = true;
new Thread(new Runnable() {
@Override
public void run() {
img = createMyImage(width, height, max_iteration, 1);
repaint();
busy = false;
}
}).start();
}
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void mouseWheelMoved(MouseWheelEvent e) {
if (!busy) {
busy = true;
int n = e.getUnitsToScroll();
regOffset += n;
regOffset = (regOffset + 256) % 256;
new Thread(new Runnable() {
@Override
public void run() {
img = createMyImage(width, height, max_iteration, 1);
repaint();
busy = false;
}
}).start();
}
}
public static void main(String[] args) {
JFrame frame = new JFrame("Mandelbrot");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(width + 8, height + 27);
frame.getContentPane().add(new Mandelbrot(frame));
frame.setVisible(true);
System.out.println("--------------------------------");
System.out.println("Welcome to Mandelbrot 2014-11-17");
System.out.println("--------------------------------");
System.out.println("use mouse to rebuild picture");
System.out.println("- left button: zoom in");
System.out.println("- right button: zoom out");
System.out.println("- middle button: save as file");
System.out.println("- scroll wheel to change color\n");
System.out.println("u key to increase max iteration");
System.out.println("d key to decrease max iteration");
}
}