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.Struct;
025    import railo.runtime.type.util.CollectionUtil;
026    
027    
028    
029    public class PointillizeFilter extends CellularFilter  implements DynFiltering {
030    
031            private float edgeThickness = 0.4f;
032            private boolean fadeEdges = false;
033            private int edgeColor = 0xff000000;
034            private float fuzziness = 0.1f;
035    
036            public PointillizeFilter() {
037                    setScale(16);
038                    setRandomness(0.0f);
039            }
040            
041            public void setEdgeThickness(float edgeThickness) {
042                    this.edgeThickness = edgeThickness;
043            }
044    
045            public float getEdgeThickness() {
046                    return edgeThickness;
047            }
048    
049            public void setFadeEdges(boolean fadeEdges) {
050                    this.fadeEdges = fadeEdges;
051            }
052    
053            public boolean getFadeEdges() {
054                    return fadeEdges;
055            }
056    
057            public void setEdgeColor(int edgeColor) {
058                    this.edgeColor = edgeColor;
059            }
060    
061            public int getEdgeColor() {
062                    return edgeColor;
063            }
064    
065            public void setFuzziness(float fuzziness) {
066                    this.fuzziness = fuzziness;
067            }
068    
069            public float getFuzziness() {
070                    return fuzziness;
071            }
072    
073            public int getPixel(int x, int y, int[] inPixels, int width, int height) {
074                    float nx = m00*x + m01*y;
075                    float ny = m10*x + m11*y;
076                    nx /= scale;
077                    ny /= scale * stretch;
078                    nx += 1000;
079                    ny += 1000;     // Reduce artifacts around 0,0
080                    float f = evaluate(nx, ny);
081    
082                    float f1 = results[0].distance;
083                    int srcx = ImageMath.clamp((int)((results[0].x-1000)*scale), 0, width-1);
084                    int srcy = ImageMath.clamp((int)((results[0].y-1000)*scale), 0, height-1);
085                    int v = inPixels[srcy * width + srcx];
086    
087                    if (fadeEdges) {
088                            float f2 = results[1].distance;
089                            srcx = ImageMath.clamp((int)((results[1].x-1000)*scale), 0, width-1);
090                            srcy = ImageMath.clamp((int)((results[1].y-1000)*scale), 0, height-1);
091                            int v2 = inPixels[srcy * width + srcx];
092                            v = ImageMath.mixColors(0.5f*f1/f2, v, v2);
093                    } else {
094                            f = 1-ImageMath.smoothStep(edgeThickness, edgeThickness+fuzziness, f1);
095                            v = ImageMath.mixColors(f, edgeColor, v);
096                    }
097                    return v;
098            }
099    
100            public String toString() {
101                    return "Stylize/Pointillize...";
102            }
103            
104            public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src);
105                    Object o;
106                    if((o=parameters.removeEL(KeyImpl.init("Fuzziness")))!=null)setFuzziness(ImageFilterUtil.toFloatValue(o,"Fuzziness"));
107                    if((o=parameters.removeEL(KeyImpl.init("EdgeThickness")))!=null)setEdgeThickness(ImageFilterUtil.toFloatValue(o,"EdgeThickness"));
108                    if((o=parameters.removeEL(KeyImpl.init("FadeEdges")))!=null)setFadeEdges(ImageFilterUtil.toBooleanValue(o,"FadeEdges"));
109                    if((o=parameters.removeEL(KeyImpl.init("EdgeColor")))!=null)setEdgeColor(ImageFilterUtil.toColorRGB(o,"EdgeColor"));
110                    if((o=parameters.removeEL(KeyImpl.init("Colormap")))!=null)setColormap(ImageFilterUtil.toColormap(o,"Colormap"));
111                    if((o=parameters.removeEL(KeyImpl.init("Amount")))!=null)setAmount(ImageFilterUtil.toFloatValue(o,"Amount"));
112                    if((o=parameters.removeEL(KeyImpl.init("Turbulence")))!=null)setTurbulence(ImageFilterUtil.toFloatValue(o,"Turbulence"));
113                    if((o=parameters.removeEL(KeyImpl.init("Stretch")))!=null)setStretch(ImageFilterUtil.toFloatValue(o,"Stretch"));
114                    if((o=parameters.removeEL(KeyImpl.init("Angle")))!=null)setAngle(ImageFilterUtil.toFloatValue(o,"Angle"));
115                    if((o=parameters.removeEL(KeyImpl.init("AngleCoefficient")))!=null)setAngleCoefficient(ImageFilterUtil.toFloatValue(o,"AngleCoefficient"));
116                    if((o=parameters.removeEL(KeyImpl.init("GradientCoefficient")))!=null)setGradientCoefficient(ImageFilterUtil.toFloatValue(o,"GradientCoefficient"));
117                    if((o=parameters.removeEL(KeyImpl.init("F1")))!=null)setF1(ImageFilterUtil.toFloatValue(o,"F1"));
118                    if((o=parameters.removeEL(KeyImpl.init("F2")))!=null)setF2(ImageFilterUtil.toFloatValue(o,"F2"));
119                    if((o=parameters.removeEL(KeyImpl.init("F3")))!=null)setF3(ImageFilterUtil.toFloatValue(o,"F3"));
120                    if((o=parameters.removeEL(KeyImpl.init("F4")))!=null)setF4(ImageFilterUtil.toFloatValue(o,"F4"));
121                    if((o=parameters.removeEL(KeyImpl.init("Randomness")))!=null)setRandomness(ImageFilterUtil.toFloatValue(o,"Randomness"));
122                    if((o=parameters.removeEL(KeyImpl.init("GridType")))!=null)setGridType(ImageFilterUtil.toString(o,"GridType"));
123                    if((o=parameters.removeEL(KeyImpl.init("DistancePower")))!=null)setDistancePower(ImageFilterUtil.toFloatValue(o,"DistancePower"));
124                    if((o=parameters.removeEL(KeyImpl.init("Scale")))!=null)setScale(ImageFilterUtil.toFloatValue(o,"Scale"));
125    
126                    // check for arguments not supported
127                    if(parameters.size()>0) {
128                            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 [Fuzziness, EdgeThickness, FadeEdges, EdgeColor, Colormap, Amount, Turbulence, Stretch, Angle, Coefficient, AngleCoefficient, GradientCoefficient, F1, F2, F3, F4, Randomness, GridType, DistancePower, Scale]");
129                    }
130    
131                    return filter(src, dst);
132            }
133    }