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.List;
025    import railo.runtime.type.Struct;
026    
027    /**
028     * A filter which removes noise from an image using a "pepper and salt" algorithm.
029     */
030    public class DespeckleFilter extends WholeImageFilter  implements DynFiltering {
031    
032            public DespeckleFilter() {
033            }
034    
035            private short pepperAndSalt( short c, short v1, short v2 ) {
036                    if ( c < v1 )
037                            c++;
038                    if ( c < v2 )
039                            c++;
040                    if ( c > v1 )
041                            c--;
042                    if ( c > v2 )
043                            c--;
044                    return c;
045            }
046            
047            protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) {
048                    int index = 0;
049                    short[][] r = new short[3][width];
050                    short[][] g = new short[3][width];
051                    short[][] b = new short[3][width];
052                    int[] outPixels = new int[width * height];
053    
054                    for (int x = 0; x < width; x++) {
055                            int rgb = inPixels[x];
056                            r[1][x] = (short)((rgb >> 16) & 0xff);
057                            g[1][x] = (short)((rgb >> 8) & 0xff);
058                            b[1][x] = (short)(rgb & 0xff);
059                    }
060                    for (int y = 0; y < height; y++) {
061                            boolean yIn = y > 0 && y < height-1;
062                            int nextRowIndex = index+width;
063                            if ( y < height-1) {
064                                    for (int x = 0; x < width; x++) {
065                                            int rgb = inPixels[nextRowIndex++];
066                                            r[2][x] = (short)((rgb >> 16) & 0xff);
067                                            g[2][x] = (short)((rgb >> 8) & 0xff);
068                                            b[2][x] = (short)(rgb & 0xff);
069                                    }
070                            }
071                            for (int x = 0; x < width; x++) {
072                                    boolean xIn = x > 0 && x < width-1;
073                                    short or = r[1][x];
074                                    short og = g[1][x];
075                                    short ob = b[1][x];
076                                    int w = x-1;
077                                    int e = x+1;
078                                    
079                                    if ( yIn ) {
080                                            or = pepperAndSalt( or, r[0][x], r[2][x] );
081                                            og = pepperAndSalt( og, g[0][x], g[2][x] );
082                                            ob = pepperAndSalt( ob, b[0][x], b[2][x] );
083                                    }
084    
085                                    if ( xIn ) {
086                                            or = pepperAndSalt( or, r[1][w], r[1][e] );
087                                            og = pepperAndSalt( og, g[1][w], g[1][e] );
088                                            ob = pepperAndSalt( ob, b[1][w], b[1][e] );
089                                    }
090    
091                                    if ( yIn && xIn ) {
092                                            or = pepperAndSalt( or, r[0][w], r[2][e] );
093                                            og = pepperAndSalt( og, g[0][w], g[2][e] );
094                                            ob = pepperAndSalt( ob, b[0][w], b[2][e] );
095    
096                                            or = pepperAndSalt( or, r[2][w], r[0][e] );
097                                            og = pepperAndSalt( og, g[2][w], g[0][e] );
098                                            ob = pepperAndSalt( ob, b[2][w], b[0][e] );
099                                    }
100    
101                                    outPixels[index] = (inPixels[index] & 0xff000000) | (or << 16) | (og << 8) | ob;
102                                    index++;
103                            }
104                            short[] t;
105                            t = r[0];
106                            r[0] = r[1];
107                            r[1] = r[2];
108                            r[2] = t;
109                            t = g[0];
110                            g[0] = g[1];
111                            g[1] = g[2];
112                            g[2] = t;
113                            t = b[0];
114                            b[0] = b[1];
115                            b[1] = b[2];
116                            b[2] = t;
117                    }
118            
119                    return outPixels;
120            }
121    
122            public String toString() {
123                    return "Blur/Despeckle...";
124            }
125    
126            public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src);
127                    Object o;
128    
129                    // check for arguments not supported
130                    if(parameters.size()>0) {
131                            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 []");
132                    }
133    
134                    return filter(src, dst);
135            }
136    }
137