// Marco13 for [url]http://www.java-forum.org/spiele-multimedia-programmierung/133653-wolken-bild-grafik-programm-erstellen-lassen.html#post878969[/url]
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
public class PerlinNoiseTest
{
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
@Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
int sizeX = 500;
int sizeY = 500;
BufferedImage image = new BufferedImage(sizeX,sizeY,BufferedImage.TYPE_INT_ARGB);
Noise noise = new MultiLevelPerlinNoise(6);
int colorMap[] = createColorMap(64, Color.RED, Color.GREEN, Color.BLUE);
fillImage(image, noise, colorMap);
f.getContentPane().setLayout(new BorderLayout());
f.getContentPane().add(new JLabel(new ImageIcon(image)));
f.pack();
f.setVisible(true);
}
private static void fillImage(BufferedImage image, Noise noise, int colorMap[])
{
int min = Integer.MAX_VALUE;
int max = -Integer.MAX_VALUE;
int resolution = Short.MAX_VALUE;
int w = image.getWidth();
int h = image.getHeight();
for (int x=0; x<w; x++)
{
for (int y=0; y<h; y++)
{
double value = noise.get((double)x/w,(double)y/h);
int v = (int)(value * resolution);
min = Math.min(min, v);
max = Math.max(max, v);
image.setRGB(x,y,v);
}
}
for (int i=0; i<w; i++)
{
for (int j=0; j<h; j++)
{
int v = image.getRGB(i, j);
double value = (double)(v-min) / (max-min);
int index = (int)(value * (colorMap.length-1));
image.setRGB(i,j,colorMap[index]);
}
}
}
private static int[] createColorMap(int stepSize, Color ... colors)
{
int colorMap[] = new int[stepSize*(colors.length-1)];
int index = 0;
for (int i=0; i<colors.length-1; i++)
{
Color c0 = colors[i];
int r0 = c0.getRed();
int g0 = c0.getGreen();
int b0 = c0.getBlue();
Color c1 = colors[i+1];
int r1 = c1.getRed();
int g1 = c1.getGreen();
int b1 = c1.getBlue();
int dr = r1-r0;
int dg = g1-g0;
int db = b1-b0;
for (int j=0; j<stepSize; j++)
{
float alpha = (float)j / (stepSize-1);
int r = (int)(r0 + alpha * dr);
int g = (int)(g0 + alpha * dg);
int b = (int)(b0 + alpha * db);
int rgb =
0xFF000000 |
(r << 16) |
(g << 8) |
(b << 0);
colorMap[index++] = rgb;
}
}
return colorMap;
}
}
interface Noise
{
double get(double x, double y);
}
class MultiLevelPerlinNoise implements Noise
{
private final List<Noise> noises;
public MultiLevelPerlinNoise(int levels)
{
noises = new ArrayList<Noise>();
for (int i=0; i<levels; i++)
{
int size = 2*(1<<i);
noises.add(new PerlinNoise(size, size));
}
}
public double get(double x, double y)
{
double z = 0;
double amplitude = 1;
double persistance = 0.5;
double totalAmplitude = 0;
for (Noise noise : noises)
{
amplitude *= persistance;
totalAmplitude += amplitude;
z += amplitude * noise.get(x, y);
}
z /= totalAmplitude;
return z;
}
}
// Based on [url=http://webstaff.itn.liu.se/~stegu/TNM022-2005/perlinnoiselinks/perlin-noise-math-faq.html]The Perlin noise math FAQ[/url]
class PerlinNoise implements Noise
{
private static final double INV_SQRT2 = 1.0/Math.sqrt(2);
private static final Random random = new Random();
private final int gridSizeX;
private final int gridSizeY;
private final Vec g[][];
public PerlinNoise(int gridSizeX, int gridSizeY)
{
this.gridSizeX = gridSizeX;
this.gridSizeY = gridSizeY;
g = new Vec[gridSizeX][gridSizeY];
for (int x=0; x<gridSizeX; x++)
{
for (int y=0; y<gridSizeY; y++)
{
g[x][y] = new Vec();
}
}
}
private static class Vec
{
double x;
double y;
private Vec()
{
x = -1 + 2 * random.nextDouble();
y = -1 + 2 * random.nextDouble();
double s = 1.0 / Math.sqrt(x*x+y*y);
x *= s;
y *= s;
}
}
@Override
public double get(double rx, double ry)
{
double x = rx * (gridSizeX-1);
double y = ry * (gridSizeY-1);
int x0 = (int)x;
int y0 = (int)y;
int x1 = x0+1;
int y1 = y0+1;
double dx0 = x-x0;
double dy0 = y-y0;
double dx1 = x-x1;
double dy1 = y-y1;
double d00 = g[x0][y0].x * dx0 + g[x0][y0].y * dy0;
double d10 = g[x1][y0].x * dx1 + g[x1][y0].y * dy0;
double d01 = g[x0][y1].x * dx0 + g[x0][y1].y * dy1;
double d11 = g[x1][y1].x * dx1 + g[x1][y1].y * dy1;
double ix = curve(dx0);
double a = d00 + ix*(d10-d00);
double b = d01 + ix*(d11-d01);
double iy = curve(dy0);
double z = a + iy*(b-a);
return 0.5 + z * INV_SQRT2;
}
private static double curve(double t)
{
return t * t * (3.0 - 2.0 * t);
}
}