001/*
002Copyright 2006 Jerry Huxtable
003
004Licensed under the Apache License, Version 2.0 (the "License");
005you may not use this file except in compliance with the License.
006You may obtain a copy of the License at
007
008   http://www.apache.org/licenses/LICENSE-2.0
009
010Unless required by applicable law or agreed to in writing, software
011distributed under the License is distributed on an "AS IS" BASIS,
012WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013See the License for the specific language governing permissions and
014limitations under the License.
015*/
016
017package com.jhlabs.image;
018
019import java.awt.*;
020import java.awt.image.*;
021
022/**
023 * A filter which removes noise from an image using a "pepper and salt" algorithm.
024 */
025public class DespeckleFilter extends WholeImageFilter {
026
027        public DespeckleFilter() {
028        }
029
030        private short pepperAndSalt( short c, short v1, short v2 ) {
031                if ( c < v1 )
032                        c++;
033                if ( c < v2 )
034                        c++;
035                if ( c > v1 )
036                        c--;
037                if ( c > v2 )
038                        c--;
039                return c;
040        }
041        
042        protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) {
043                int index = 0;
044                short[][] r = new short[3][width];
045                short[][] g = new short[3][width];
046                short[][] b = new short[3][width];
047                int[] outPixels = new int[width * height];
048
049                for (int x = 0; x < width; x++) {
050                        int rgb = inPixels[x];
051                        r[1][x] = (short)((rgb >> 16) & 0xff);
052                        g[1][x] = (short)((rgb >> 8) & 0xff);
053                        b[1][x] = (short)(rgb & 0xff);
054                }
055                for (int y = 0; y < height; y++) {
056                        boolean yIn = y > 0 && y < height-1;
057                        int nextRowIndex = index+width;
058                        if ( y < height-1) {
059                                for (int x = 0; x < width; x++) {
060                                        int rgb = inPixels[nextRowIndex++];
061                                        r[2][x] = (short)((rgb >> 16) & 0xff);
062                                        g[2][x] = (short)((rgb >> 8) & 0xff);
063                                        b[2][x] = (short)(rgb & 0xff);
064                                }
065                        }
066                        for (int x = 0; x < width; x++) {
067                                boolean xIn = x > 0 && x < width-1;
068                                short or = r[1][x];
069                                short og = g[1][x];
070                                short ob = b[1][x];
071                                int w = x-1;
072                                int e = x+1;
073                                
074                                if ( yIn ) {
075                                        or = pepperAndSalt( or, r[0][x], r[2][x] );
076                                        og = pepperAndSalt( og, g[0][x], g[2][x] );
077                                        ob = pepperAndSalt( ob, b[0][x], b[2][x] );
078                                }
079
080                                if ( xIn ) {
081                                        or = pepperAndSalt( or, r[1][w], r[1][e] );
082                                        og = pepperAndSalt( og, g[1][w], g[1][e] );
083                                        ob = pepperAndSalt( ob, b[1][w], b[1][e] );
084                                }
085
086                                if ( yIn && xIn ) {
087                                        or = pepperAndSalt( or, r[0][w], r[2][e] );
088                                        og = pepperAndSalt( og, g[0][w], g[2][e] );
089                                        ob = pepperAndSalt( ob, b[0][w], b[2][e] );
090
091                                        or = pepperAndSalt( or, r[2][w], r[0][e] );
092                                        og = pepperAndSalt( og, g[2][w], g[0][e] );
093                                        ob = pepperAndSalt( ob, b[2][w], b[0][e] );
094                                }
095
096                                outPixels[index] = (inPixels[index] & 0xff000000) | (or << 16) | (og << 8) | ob;
097                                index++;
098                        }
099                        short[] t;
100                        t = r[0];
101                        r[0] = r[1];
102                        r[1] = r[2];
103                        r[2] = t;
104                        t = g[0];
105                        g[0] = g[1];
106                        g[1] = g[2];
107                        g[2] = t;
108                        t = b[0];
109                        b[0] = b[1];
110                        b[1] = b[2];
111                        b[2] = t;
112                }
113        
114                return outPixels;
115        }
116
117        public String toString() {
118                return "Blur/Despeckle...";
119        }
120
121}
122