import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.MultipleGradientPaint.CycleMethod;
import java.awt.Point;
import java.awt.RadialGradientPaint;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Point2D;
import java.awt.image.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
class LightEffectPanel4 extends JPanel implements MouseMotionListener
{
private Point point = new Point(0,0);
private BufferedImage inImage;
private BufferedImage lightsImage;
private BufferedImage lightImage;
private BufferedImage outImage;
public LightEffectPanel4()
{
inImage = loadInputImage();
int w = inImage.getWidth();
int h = inImage.getHeight();
lightsImage = new BufferedImage(w,h,
BufferedImage.TYPE_INT_ARGB);
lightImage = new BufferedImage(w,h,
BufferedImage.TYPE_INT_ARGB);
outImage = new BufferedImage(w,h,
BufferedImage.TYPE_INT_ARGB);
addMouseMotionListener(this);
}
private BufferedImage loadInputImage()
{
BufferedImage i = null;
try {
i = ImageIO.read(new File("img.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
BufferedImage image = new BufferedImage(i.getWidth(), i.getHeight(),
BufferedImage.TYPE_INT_ARGB);
Graphics2D g = image.createGraphics();
g.drawImage(i,0,0,null);
//g.setColor(Color.WHITE);
//g.fillRect(0,0,i.getWidth(),i.getHeight());
g.dispose();
return image;
}
@Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
Graphics2D g = (Graphics2D)gr;
drawLights();
multiply(inImage, lightsImage, outImage);
g.drawImage(outImage, 0,0,null);
}
private void drawLights()
{
Graphics2D g = lightsImage.createGraphics();
g.setColor(Color.BLACK);
g.fillRect(0,0,lightsImage.getWidth(),lightsImage.getHeight());
g.dispose();
drawLight(point, new Color(255,230,128));
drawLight(new Point(190,210), Color.RED);
drawLight(new Point(160,180), Color.GREEN);
drawLight(new Point(220,180), Color.BLUE);
}
private void drawLight(Point pt, Color color)
{
int radius = 100;
Point2D center = new Point2D.Float(pt.x, pt.y);
Color black = new Color(0,0,0,0);
int steps = 10;
float[] dist = new float[steps];
Color[] colors = new Color[steps];
boolean quadratic = true;
for (int i=0; i<steps; i++)
{
float x = (float)i / (steps-1);
dist[i] = x;
float y = x;
if (quadratic)
{
y *= x;
}
colors[i] = interpolate(color, black, y);
}
RadialGradientPaint p =
new RadialGradientPaint(
center, radius, dist, colors, CycleMethod.NO_CYCLE);
Graphics2D g = lightImage.createGraphics();
g.setColor(Color.BLACK);
g.fillRect(0,0,lightImage.getWidth(),lightImage.getHeight());
g.setPaint(p);
g.fillOval(pt.x-radius,pt.y-radius,radius*2,radius*2);
g.dispose();
add(lightsImage, lightImage, lightsImage);
}
@Override
public void mouseDragged(MouseEvent e) {
}
@Override
public void mouseMoved(MouseEvent e) {
point = e.getPoint();
repaint();
}
private static Color interpolate(Color c0, Color c1, float t)
{
int a0 = c0.getAlpha();
int r0 = c0.getRed();
int g0 = c0.getGreen();
int b0 = c0.getBlue();
int a1 = c1.getAlpha();
int r1 = c1.getRed();
int g1 = c1.getGreen();
int b1 = c1.getBlue();
int da = a1-a0;
int dr = r1-r0;
int dg = g1-g0;
int db = b1-b0;
int a = (int)(a0 + da * t);
int r = (int)(r0 + dr * t);
int g = (int)(g0 + dg * t);
int b = (int)(b0 + db * t);
return new Color(r,g,b,a);
}
private static int[] getData(BufferedImage i)
{
Raster raster = i.getRaster();
DataBuffer dataBuffer = raster.getDataBuffer();
if (!(dataBuffer instanceof DataBufferInt))
{
throw new IllegalArgumentException(
"Image does not have a DataBufferInt");
}
DataBufferInt dataBufferInt = (DataBufferInt)dataBuffer;
int data[] = dataBufferInt.getData();
return data;
}
private static int getA(int argb) { return (argb >> 24) & 0xFF; }
private static int getR(int argb) { return (argb >> 16) & 0xFF; }
private static int getG(int argb) { return (argb >> 8) & 0xFF; }
private static int getB(int argb) { return (argb >> 0) & 0xFF; }
private static int getARGB(int a, int r, int g, int b)
{
return (a << 24) | (r << 16) | (g << 8) | (b << 0);
}
private static void multiply(BufferedImage i0, BufferedImage i1, BufferedImage result)
{
int data0[] = getData(i0);
int data1[] = getData(i1);
int dataResult[] = getData(result);
int w = i0.getWidth();
int h = i0.getHeight();
for (int x=0; x<w; x++)
{
for (int y=0;y<h; y++)
{
int argb0 = data0[x+y*w];
int a0 = getA(argb0);
int r0 = getR(argb0);
int g0 = getG(argb0);
int b0 = getB(argb0);
int argb1 = data1[x+y*w];
int a1 = getA(argb1);
int r1 = getR(argb1);
int g1 = getG(argb1);
int b1 = getB(argb1);
int ar = (a0*a1) >> 8;
int rr = (r0*r1) >> 8;
int gr = (g0*g1) >> 8;
int br = (b0*b1) >> 8;
int argb = getARGB(ar, rr, gr, br);
dataResult[x+y*w] = argb;
}
}
}
private static void add(BufferedImage i0, BufferedImage i1, BufferedImage result)
{
int data0[] = getData(i0);
int data1[] = getData(i1);
int dataResult[] = getData(result);
int w = i0.getWidth();
int h = i0.getHeight();
for (int x=0; x<w; x++)
{
for (int y=0;y<h; y++)
{
int argb0 = data0[x+y*w];
int a0 = getA(argb0);
int r0 = getR(argb0);
int g0 = getG(argb0);
int b0 = getB(argb0);
int argb1 = data1[x+y*w];
int a1 = getA(argb1);
int r1 = getR(argb1);
int g1 = getG(argb1);
int b1 = getB(argb1);
int ar = Math.min(255, a0+a1);
int rr = Math.min(255, r0+r1);
int gr = Math.min(255, g0+g1);
int br = Math.min(255, b0+b1);
int argb = getARGB(ar, rr, gr, br);
dataResult[x+y*w] = argb;
}
}
}
}
class LightEffectTest4
{
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
new LightEffectTest4();
}
});
}
public LightEffectTest4()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.getContentPane().add(new LightEffectPanel4());
f.setSize(600,600);
f.setVisible(true);
}
}