001/* 002Copyright 2006 Jerry Huxtable 003 004Licensed under the Apache License, Version 2.0 (the "License"); 005you may not use this file except in compliance with the License. 006You may obtain a copy of the License at 007 008 http://www.apache.org/licenses/LICENSE-2.0 009 010Unless required by applicable law or agreed to in writing, software 011distributed under the License is distributed on an "AS IS" BASIS, 012WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013See the License for the specific language governing permissions and 014limitations under the License. 015*/ 016 017package com.jhlabs.image; 018 019import java.awt.geom.*; 020import java.awt.image.*; 021import java.util.*; 022import com.jhlabs.math.*; 023 024/** 025 * An experimental filter for rendering lens flares. 026 */ 027public class FlareFilter extends PointFilter { 028 029 private int rays = 50; 030 private float radius; 031 private float baseAmount = 1.0f; 032 private float ringAmount = 0.2f; 033 private float rayAmount = 0.1f; 034 private int color = 0xffffffff; 035 private int width, height; 036 private float centreX = 0.5f, centreY = 0.5f; 037 private float ringWidth = 1.6f; 038 039 private float linear = 0.03f; 040 private float gauss = 0.006f; 041 private float mix = 0.50f; 042 private float falloff = 6.0f; 043 private float sigma; 044 045 private float icentreX, icentreY; 046 047 public FlareFilter() { 048 setRadius(50.0f); 049 } 050 051 public void setColor(int color) { 052 this.color = color; 053 } 054 055 public int getColor() { 056 return color; 057 } 058 059 public void setRingWidth(float ringWidth) { 060 this.ringWidth = ringWidth; 061 } 062 063 public float getRingWidth() { 064 return ringWidth; 065 } 066 067 public void setBaseAmount(float baseAmount) { 068 this.baseAmount = baseAmount; 069 } 070 071 public float getBaseAmount() { 072 return baseAmount; 073 } 074 075 public void setRingAmount(float ringAmount) { 076 this.ringAmount = ringAmount; 077 } 078 079 public float getRingAmount() { 080 return ringAmount; 081 } 082 083 public void setRayAmount(float rayAmount) { 084 this.rayAmount = rayAmount; 085 } 086 087 public float getRayAmount() { 088 return rayAmount; 089 } 090 091 public void setCentre( Point2D centre ) { 092 this.centreX = (float)centre.getX(); 093 this.centreY = (float)centre.getY(); 094 } 095 096 public Point2D getCentre() { 097 return new Point2D.Float( centreX, centreY ); 098 } 099 100 /** 101 * Set the radius of the effect. 102 * @param radius the radius 103 * @min-value 0 104 * @see #getRadius 105 */ 106 public void setRadius(float radius) { 107 this.radius = radius; 108 sigma = radius/3; 109 } 110 111 /** 112 * Get the radius of the effect. 113 * @return the radius 114 * @see #setRadius 115 */ 116 public float getRadius() { 117 return radius; 118 } 119 120 public void setDimensions(int width, int height) { 121 this.width = width; 122 this.height = height; 123 icentreX = centreX*width; 124 icentreY = centreY*height; 125 super.setDimensions(width, height); 126 } 127 128 public int filterRGB(int x, int y, int rgb) { 129 float dx = x-icentreX; 130 float dy = y-icentreY; 131 float distance = (float)Math.sqrt(dx*dx+dy*dy); 132 float a = (float)Math.exp(-distance*distance*gauss)*mix + (float)Math.exp(-distance*linear)*(1-mix); 133 float ring; 134 135 a *= baseAmount; 136 137 if (distance > radius + ringWidth) 138 a = ImageMath.lerp((distance - (radius + ringWidth))/falloff, a, 0); 139 140 if (distance < radius - ringWidth || distance > radius + ringWidth) 141 ring = 0; 142 else { 143 ring = Math.abs(distance-radius)/ringWidth; 144 ring = 1 - ring*ring*(3 - 2*ring); 145 ring *= ringAmount; 146 } 147 148 a += ring; 149 150 float angle = (float)Math.atan2(dx, dy)+ImageMath.PI; 151 angle = (ImageMath.mod(angle/ImageMath.PI*17 + 1.0f + Noise.noise1(angle*10), 1.0f) - 0.5f)*2; 152 angle = Math.abs(angle); 153 angle = (float)Math.pow(angle, 5.0); 154 155 float b = rayAmount * angle / (1 + distance*0.1f); 156 a += b; 157 158 a = ImageMath.clamp(a, 0, 1); 159 return ImageMath.mixColors(a, rgb, color); 160 } 161 162 public String toString() { 163 return "Stylize/Flare..."; 164 } 165}