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.Rectangle;
018    import java.awt.image.BufferedImage;
019    
020    import railo.runtime.engine.ThreadLocalPageContext;
021    import railo.runtime.exp.FunctionException;
022    import railo.runtime.exp.PageException;
023    import railo.runtime.img.ImageUtil;
024    import railo.runtime.type.KeyImpl;
025    import railo.runtime.type.Struct;
026    import railo.runtime.type.util.CollectionUtil;
027    
028    /**
029     * Given a binary image, this filter performs binary dilation, setting all added pixels to the given 'new' color.
030     */
031    public class DilateFilter extends BinaryFilter  implements DynFiltering {
032    
033            private int threshold = 2;
034    
035            public DilateFilter() {
036            }
037    
038            /**
039             * Set the threshold - the number of neighbouring pixels for dilation to occur.
040             * @param threshold the new threshold
041         * @see #getThreshold
042             */
043            public void setThreshold(int threshold) {
044                    this.threshold = threshold;
045            }
046            
047            /**
048             * Return the threshold - the number of neighbouring pixels for dilation to occur.
049             * @return the current threshold
050         * @see #setThreshold
051             */
052            public int getThreshold() {
053                    return threshold;
054            }
055            
056            protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) {
057                    int[] outPixels = new int[width * height];
058    
059                    for (int i = 0; i < iterations; i++) {
060                            int index = 0;
061    
062                            if (i > 0) {
063                                    int[] t = inPixels;
064                                    inPixels = outPixels;
065                                    outPixels = t;
066                            }
067                            for (int y = 0; y < height; y++) {
068                                    for (int x = 0; x < width; x++) {
069                                            int pixel = inPixels[y*width+x];
070                                            if (!blackFunction.isBlack(pixel)) {
071                                                    int neighbours = 0;
072    
073                                                    for (int dy = -1; dy <= 1; dy++) {
074                                                            int iy = y+dy;
075                                                            int ioffset;
076                                                            if (0 <= iy && iy < height) {
077                                                                    ioffset = iy*width;
078                                                                    for (int dx = -1; dx <= 1; dx++) {
079                                                                            int ix = x+dx;
080                                                                            if (!(dy == 0 && dx == 0) && 0 <= ix && ix < width) {
081                                                                                    int rgb = inPixels[ioffset+ix];
082                                                                                    if (blackFunction.isBlack(rgb))
083                                                                                            neighbours++;
084                                                                            }
085                                                                    }
086                                                            }
087                                                    }
088                                                    
089                                                    if (neighbours >= threshold) {
090                                                            if (colormap != null)
091                                                                    pixel = colormap.getColor((float)i/iterations);
092                                                            else
093                                                                    pixel = newColor;
094                                                    }
095                                            }
096                                            outPixels[index++] = pixel;
097                                    }
098                            }
099                    }
100                    return outPixels;
101            }
102    
103            public String toString() {
104                    return "Binary/Dilate...";
105            }
106    
107            public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src);
108                    Object o;
109                    if((o=parameters.removeEL(KeyImpl.init("Threshold")))!=null)setThreshold(ImageFilterUtil.toIntValue(o,"Threshold"));
110                    if((o=parameters.removeEL(KeyImpl.init("Iterations")))!=null)setIterations(ImageFilterUtil.toIntValue(o,"Iterations"));
111                    if((o=parameters.removeEL(KeyImpl.init("Colormap")))!=null)setColormap(ImageFilterUtil.toColormap(o,"Colormap"));
112                    if((o=parameters.removeEL(KeyImpl.init("NewColor")))!=null)setNewColor(ImageFilterUtil.toColorRGB(o,"NewColor"));
113                    
114                    // check for arguments not supported
115                    if(parameters.size()>0) {
116                            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 [Threshold, Iterations, Colormap, NewColor, BlackFunction]");
117                    }
118    
119                    return filter(src, dst);
120            }
121    }
122