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.*;
020import java.awt.geom.*;
021import java.awt.image.*;
022import com.jhlabs.composite.*;
023
024public class ShineFilter extends AbstractBufferedImageOp {
025        
026        private float radius = 5;
027        private float angle = (float)Math.PI*7/4;
028        private float distance = 5;
029        private float bevel = 0.5f;
030        private boolean shadowOnly = false;
031        private int shineColor = 0xffffffff;
032        private float brightness = 0.2f;
033        private float softness = 0;
034
035        public ShineFilter() {
036        }
037
038        public void setAngle(float angle) {
039                this.angle = angle;
040        }
041
042        public float getAngle() {
043                return angle;
044        }
045
046        public void setDistance(float distance) {
047                this.distance = distance;
048        }
049
050        public float getDistance() {
051                return distance;
052        }
053
054        /**
055         * Set the radius of the kernel, and hence the amount of blur. The bigger the radius, the longer this filter will take.
056         * @param radius the radius of the blur in pixels.
057         */
058        public void setRadius(float radius) {
059                this.radius = radius;
060        }
061        
062        /**
063         * Get the radius of the kernel.
064         * @return the radius
065         */
066        public float getRadius() {
067                return radius;
068        }
069
070        public void setBevel(float bevel) {
071                this.bevel = bevel;
072        }
073
074        public float getBevel() {
075                return bevel;
076        }
077
078        public void setShineColor(int shineColor) {
079                this.shineColor = shineColor;
080        }
081
082        public int getShineColor() {
083                return shineColor;
084        }
085
086        public void setShadowOnly(boolean shadowOnly) {
087                this.shadowOnly = shadowOnly;
088        }
089
090        public boolean getShadowOnly() {
091                return shadowOnly;
092        }
093
094        public void setBrightness(float brightness) {
095                this.brightness = brightness;
096        }
097        
098        public float getBrightness() {
099                return brightness;
100        }
101        
102        public void setSoftness(float softness) {
103                this.softness = softness;
104        }
105
106        public float getSoftness() {
107                return softness;
108        }
109
110    public BufferedImage filter( BufferedImage src, BufferedImage dst ) {
111        int width = src.getWidth();
112        int height = src.getHeight();
113
114        if ( dst == null )
115            dst = createCompatibleDestImage( src, null );
116
117                float xOffset = distance*(float)Math.cos(angle);
118                float yOffset = -distance*(float)Math.sin(angle);
119
120        BufferedImage matte = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
121        ErodeAlphaFilter s = new ErodeAlphaFilter( bevel * 10, 0.75f, 0.1f );
122        matte = s.filter( src, null );
123
124        BufferedImage shineLayer = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
125                Graphics2D g = shineLayer.createGraphics();
126                g.setColor( new Color( shineColor ) );
127        g.fillRect( 0, 0, width, height );
128        g.setComposite( AlphaComposite.DstIn );
129        g.drawRenderedImage( matte, null );
130        g.setComposite( AlphaComposite.DstOut );
131        g.translate( xOffset, yOffset );
132        g.drawRenderedImage( matte, null );
133                g.dispose();
134        shineLayer = new GaussianFilter( radius ).filter( shineLayer, null );
135        shineLayer = new RescaleFilter( 3*brightness ).filter( shineLayer, shineLayer );
136
137                g = dst.createGraphics();
138        g.drawRenderedImage( src, null );
139        g.setComposite( new AddComposite( 1.0f ) );
140        g.drawRenderedImage( shineLayer, null );
141                g.dispose();
142
143        return dst;
144        }
145
146        public String toString() {
147                return "Stylize/Shine...";
148        }
149}