001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019/*
020*
021
022Licensed under the Apache License, Version 2.0 (the "License");
023you may not use this file except in compliance with the License.
024You may obtain a copy of the License at
025
026   http://www.apache.org/licenses/LICENSE-2.0
027
028Unless required by applicable law or agreed to in writing, software
029distributed under the License is distributed on an "AS IS" BASIS,
030WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
031See the License for the specific language governing permissions and
032limitations under the License.
033*/
034
035package lucee.runtime.img.filter;import java.awt.image.BufferedImage;
036
037import lucee.runtime.engine.ThreadLocalPageContext;
038import lucee.runtime.exp.FunctionException;
039import lucee.runtime.exp.PageException;
040import lucee.runtime.img.ImageUtil;
041import lucee.runtime.type.KeyImpl;
042import lucee.runtime.type.Struct;
043import lucee.runtime.type.util.CollectionUtil;
044
045
046
047public class FadeFilter extends PointFilter  implements DynFiltering {
048
049        //private int width, height;
050        private float angle = 0.0f;
051        private float fadeStart = 1.0f;
052        private float fadeWidth = 10.0f;
053        private int sides;
054        private boolean invert;
055        private float m00 = 1.0f;
056        private float m01 = 0.0f;
057        private float m10 = 0.0f;
058        private float m11 = 1.0f;
059
060        /**
061     * Specifies the angle of the texture.
062     * @param angle the angle of the texture.
063     * @angle
064     * @see #getAngle
065     */
066        public void setAngle(float angle) {
067                this.angle = angle;
068                float cos = (float)Math.cos(angle);
069                float sin = (float)Math.sin(angle);
070                m00 = cos;
071                m01 = sin;
072                m10 = -sin;
073                m11 = cos;
074        }
075
076        /**
077     * Returns the angle of the texture.
078     * @return the angle of the texture.
079     * @see #setAngle
080     */
081        public float getAngle() {
082                return angle;
083        }
084
085        public void setSides(int sides) {
086                this.sides = sides;
087        }
088
089        public int getSides() {
090                return sides;
091        }
092
093        public void setFadeStart(float fadeStart) {
094                this.fadeStart = fadeStart;
095        }
096
097        public float getFadeStart() {
098                return fadeStart;
099        }
100
101        public void setFadeWidth(float fadeWidth) {
102                this.fadeWidth = fadeWidth;
103        }
104
105        public float getFadeWidth() {
106                return fadeWidth;
107        }
108
109        public void setInvert(boolean invert) {
110                this.invert = invert;
111        }
112
113        public boolean getInvert() {
114                return invert;
115        }
116
117        public void setDimensions(int width, int height) {
118                //this.width = width;
119                //this.height = height;
120                super.setDimensions(width, height);
121        }
122        
123        public int filterRGB(int x, int y, int rgb) {
124                float nx = m00*x + m01*y;
125                float ny = m10*x + m11*y;
126                if (sides == 2)
127                        nx = (float)Math.sqrt(nx*nx + ny*ny);
128                else if (sides == 3)
129                        nx = ImageMath.mod(nx, 16);
130                else if (sides == 4)
131                        nx = symmetry(nx, 16);
132                int alpha = (int)(ImageMath.smoothStep(fadeStart, fadeStart+fadeWidth, nx) * 255);
133                if (invert)
134                        alpha = 255-alpha;
135                return (alpha << 24) | (rgb & 0x00ffffff);
136        }
137
138        public float symmetry(float x, float b) {
139/*
140                int d = (int)(x / b);
141                x = ImageMath.mod(x, b);
142                if ((d & 1) == 1)
143                        return b-x;
144                return x;
145*/
146                x = ImageMath.mod(x, 2*b);
147                if (x > b)
148                        return 2*b-x;
149                return x;
150        }
151        
152/*
153        public float star(float x, float y, int sides, float rMin, float rMax) {
154                float sideAngle = 2*Math.PI / sides;
155                float angle = Math.atan2(y, x);
156                float r = Math.sqrt(x*x + y*y);
157                float t = ImageMath.mod(angle, sideAngle) / sideAngle;
158                if (t > 0.5)
159                        t = 1.0-t;
160        }
161*/
162
163        public String toString() {
164                return "Fade...";
165        }
166
167        public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src);
168                Object o;
169                if((o=parameters.removeEL(KeyImpl.init("Angle")))!=null)setAngle(ImageFilterUtil.toFloatValue(o,"Angle"));
170                if((o=parameters.removeEL(KeyImpl.init("Sides")))!=null)setSides(ImageFilterUtil.toIntValue(o,"Sides"));
171                if((o=parameters.removeEL(KeyImpl.init("FadeStart")))!=null)setFadeStart(ImageFilterUtil.toFloatValue(o,"FadeStart"));
172                if((o=parameters.removeEL(KeyImpl.init("FadeWidth")))!=null)setFadeWidth(ImageFilterUtil.toFloatValue(o,"FadeWidth"));
173                if((o=parameters.removeEL(KeyImpl.init("Invert")))!=null)setInvert(ImageFilterUtil.toBooleanValue(o,"Invert"));
174                if((o=parameters.removeEL(KeyImpl.init("Dimensions")))!=null){
175                        int[] dim=ImageFilterUtil.toDimensions(o,"Dimensions");
176                        setDimensions(dim[0],dim[1]);
177                }
178
179                // check for arguments not supported
180                if(parameters.size()>0) {
181                        throw new FunctionException(ThreadLocalPageContext.get(), "ImageFilter", 3, "parameters", "the parameter"+(parameters.size()>1?"s":"")+" ["+CollectionUtil.getKeyList(parameters,", ")+"] "+(parameters.size()>1?"are":"is")+" not allowed, only the following parameters are supported [Angle, Sides, FadeStart, FadeWidth, Invert, Dimensions]");
182                }
183
184                return filter(src, dst);
185        }
186}
187