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