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.image.*;
020import java.util.*;
021
022public class SparkleFilter extends PointFilter {
023        
024        private int rays = 50;
025        private int radius = 25;
026        private int amount = 50;
027        private int color = 0xffffffff;
028        private int randomness = 25;
029        private int width, height;
030        private int centreX, centreY;
031        private long seed = 371;
032        private float[] rayLengths;
033        private Random randomNumbers = new Random();
034        
035        public SparkleFilter() {
036        }
037
038        public void setColor(int color) {
039                this.color = color;
040        }
041
042        public int getColor() {
043                return color;
044        }
045
046        public void setRandomness(int randomness) {
047                this.randomness = randomness;
048        }
049
050        public int getRandomness() {
051                return randomness;
052        }
053
054        /**
055         * Set the amount of sparkle.
056         * @param amount the amount
057     * @min-value 0
058     * @max-value 1
059     * @see #getAmount
060         */
061        public void setAmount(int amount) {
062                this.amount = amount;
063        }
064        
065        /**
066         * Get the amount of sparkle.
067         * @return the amount
068     * @see #setAmount
069         */
070        public int getAmount() {
071                return amount;
072        }
073        
074        public void setRays(int rays) {
075                this.rays = rays;
076        }
077
078        public int getRays() {
079                return rays;
080        }
081
082        /**
083         * Set the radius of the effect.
084         * @param radius the radius
085     * @min-value 0
086     * @see #getRadius
087         */
088        public void setRadius(int radius) {
089                this.radius = radius;
090        }
091
092        /**
093         * Get the radius of the effect.
094         * @return the radius
095     * @see #setRadius
096         */
097        public int getRadius() {
098                return radius;
099        }
100
101        public void setDimensions(int width, int height) {
102                this.width = width;
103                this.height = height;
104                centreX = width/2;
105                centreY = height/2;
106                super.setDimensions(width, height);
107                randomNumbers.setSeed(seed);
108                rayLengths = new float[rays];
109                for (int i = 0; i < rays; i++)
110                        rayLengths[i] = radius + randomness / 100.0f * radius * (float)randomNumbers.nextGaussian();
111        }
112        
113        public int filterRGB(int x, int y, int rgb) {
114                float dx = x-centreX;
115                float dy = y-centreY;
116                float distance = dx*dx+dy*dy;
117                float angle = (float)Math.atan2(dy, dx);
118                float d = (angle+ImageMath.PI) / (ImageMath.TWO_PI) * rays;
119                int i = (int)d;
120                float f = d - i;
121
122                if (radius != 0) {
123                        float length = ImageMath.lerp(f, rayLengths[i % rays], rayLengths[(i+1) % rays]);
124                        float g = length*length / (distance+0.0001f);
125                        g = (float)Math.pow(g, (100-amount) / 50.0);
126                        f -= 0.5f;
127//                      f *= amount/50.0f;
128                        f = 1 - f*f;
129                        f *= g;
130                }
131                f = ImageMath.clamp(f, 0, 1);
132                return ImageMath.mixColors(f, rgb, color);
133        }
134
135        public String toString() {
136                return "Stylize/Sparkle...";
137        }
138}