Code:
import java.awt.*;
import java.awt.image.*;
public class Gradient {
public static final int NONE = -1;
public static final int LINEAR = 0;
public static final int LINEAR_IN_OUT = 1;
public static final int CIRCLE = 2;
public static final int STARBURST = 3;
public static final int RADIATE = 4;
private static BufferedImage bimg;
private Gradient(){}
public static void createGradient(BufferedImage bimg, int gradientType, Color start, Color end) {
int w = bimg.getWidth();
int h = bimg.getHeight();
createGradient(bimg, gradientType, start, end, 0, 0, 0.0, Double.MAX_VALUE);
}
public static void createGradient(BufferedImage bimg, int gradientType, Color start, Color end, int cX, int cY, double rotate) {
int w = bimg.getWidth();
int h = bimg.getHeight();
createGradient(bimg, gradientType, start, end, cX, cY, rotate, Double.MAX_VALUE);
}
public static void createGradient(BufferedImage bimg, int gradientType, Color start, Color end, int cX, int cY, double rotate, double rMax) {
Gradient.bimg = bimg;
int w = bimg.getWidth();
int h = bimg.getHeight();
if(gradientType==NONE) {
int clear = new Color(0, 0, 0, 0).getRGB();
for(int i=0; i<w; ++i)
for(int j=0; j<h; ++j)
bimg.setRGB(i, j, clear);
return;
}
double r;
double[][] rs = new double[w][h];
double th, thMax = Math.PI*2, thInc = thMax/5000;
int xIndex = 0, yIndex;
double[][] zs = new double[w][h];
double z, zMin = 0, zMax = 0;
int[] colors = new int[256];
{
double red = start.getRed();
double green = start.getGreen();
double blue = start.getBlue();
double alpha = start.getAlpha();
double redInc = (end.getRed() - red) / 256.0;
double greenInc = (end.getGreen() - green) / 256.0;
double blueInc = (end.getBlue() - blue) / 256.0;
double alphaInc = (end.getAlpha() - alpha) / 256.0;
for(int i=0, n=colors.length; i<n; ++i) {
colors[i] = new Color(
(int)Math.round(red+redInc),
(int)Math.round(green+greenInc),
(int)Math.round(blue+blueInc),
(int)Math.round(alpha+alphaInc)
).getRGB();
red += redInc;
green += greenInc;
blue += blueInc;
alpha += alphaInc;
}
}
double[] colorBreakpts = new double[colors.length];
for(double x=-w/2-cX; x<w/2-cX; ++x, ++xIndex) {
yIndex = h-1;
for(double y=-w/2-cY; y<w/2-cY; ++y, --yIndex) {
r = Math.sqrt(x*x + y*y);
rs[xIndex][yIndex] = r;
if(r>rMax) continue;
th = normalizeAngle(Math.atan2(y, x) - rotate);
z = getZValue(r, th, gradientType);
zs[xIndex][yIndex] = z;
if(z<zMin) zMin = z;
else if(z>zMax) zMax = z;
}
}
double zInc = (zMax-zMin)/colorBreakpts.length;
z = zMin;
for(int i=0, n=colorBreakpts.length; i<n; ++i) {
z += zInc;
colorBreakpts[i] = z;
}
for(int x=0; x<w; ++x) {
for(int y=0; y<h; ++y) {
if(rs[x][y]<=rMax) {
z = zs[x][y];
for(int i=0, n=colorBreakpts.length; i<n; ++i) {
if(z<=colorBreakpts[i]) {
bimg.setRGB(x, y, colors[i]);
break;
}
}
}
else bimg.setRGB(x, y, Color.BLACK.getRGB());
}
}
}
private static double getZValue(double r, double th, int gradientType) {
switch(gradientType) {
case CIRCLE:
return circle(r, th);
case LINEAR:
return linear(r, th);
case LINEAR_IN_OUT:
return linearInOut(r, th);
case STARBURST:
//need to make this function
case RADIATE:
return radiate(r, th);
}
assert false;
return 0.0;
}
private static double normalizeAngle(double th) {
while(th>=Math.PI*2) th -= Math.PI*2;
while(th<0) th += Math.PI*2;
return th;
}
private static double linear(double r, double th) {
return (r*Math.cos(th)-r*Math.sin(th));
}
private static double linearInOut(double r, double th) {
if(th>Math.PI/4 && th<=Math.PI*5/4)
return (r*Math.cos(th)-r*Math.sin(th));
return -(r*Math.cos(th)-r*Math.sin(th));
}
private static double circle(double r, double th) {
return -Math.pow(r, 3/2);
}
private static double radiate(double r, double th) {
return Math.min(Math.abs(th-Math.PI/4+0.01), Math.abs(th-Math.PI*7/4-0.01));
}
}
Bookmarks