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 * An edge-detection filter.
024 */
025public class EdgeFilter extends WholeImageFilter {
026        
027        public final static float R2 = (float)Math.sqrt(2);
028
029        public final static float[] ROBERTS_V = {
030                0,  0, -1,
031                0,  1,  0,
032                0,  0,  0,
033        };
034        public final static float[] ROBERTS_H = {
035                -1,  0,  0,
036                0,  1,  0,
037                0,  0,  0,
038        };
039        public final static float[] PREWITT_V = {
040                -1,  0,  1,
041                -1,  0,  1,
042                -1,  0,  1,
043        };
044        public final static float[] PREWITT_H = {
045                -1, -1, -1,
046                0,  0,  0,
047                1,  1,  1,
048        };
049        public final static float[] SOBEL_V = {
050                -1,  0,  1,
051                -2,  0,  2,
052                -1,  0,  1,
053        };
054        public static float[] SOBEL_H = {
055                -1, -2, -1,
056                0,  0,  0,
057                1,  2,  1,
058        };
059        public final static float[] FREI_CHEN_V = {
060                -1,  0,  1,
061                -R2,  0,  R2,
062                -1,  0,  1,
063        };
064        public static float[] FREI_CHEN_H = {
065                -1, -R2, -1,
066                0,  0,  0,
067                1,  R2,  1,
068        };
069
070        protected float[] vEdgeMatrix = SOBEL_V;
071        protected float[] hEdgeMatrix = SOBEL_H;
072
073        public EdgeFilter() {
074        }
075
076        public void setVEdgeMatrix(float[] vEdgeMatrix) {
077                this.vEdgeMatrix = vEdgeMatrix;
078        }
079
080        public float[] getVEdgeMatrix() {
081                return vEdgeMatrix;
082        }
083
084        public void setHEdgeMatrix(float[] hEdgeMatrix) {
085                this.hEdgeMatrix = hEdgeMatrix;
086        }
087
088        public float[] getHEdgeMatrix() {
089                return hEdgeMatrix;
090        }
091
092        protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) {
093                int index = 0;
094                int[] outPixels = new int[width * height];
095
096                for (int y = 0; y < height; y++) {
097                        for (int x = 0; x < width; x++) {
098                                int r = 0, g = 0, b = 0;
099                                int rh = 0, gh = 0, bh = 0;
100                                int rv = 0, gv = 0, bv = 0;
101                                int a = inPixels[y*width+x] & 0xff000000;
102
103                                for (int row = -1; row <= 1; row++) {
104                                        int iy = y+row;
105                                        int ioffset;
106                                        if (0 <= iy && iy < height)
107                                                ioffset = iy*width;
108                                        else
109                                                ioffset = y*width;
110                                        int moffset = 3*(row+1)+1;
111                                        for (int col = -1; col <= 1; col++) {
112                                                int ix = x+col;
113                                                if (!(0 <= ix && ix < width))
114                                                        ix = x;
115                                                int rgb = inPixels[ioffset+ix];
116                                                float h = hEdgeMatrix[moffset+col];
117                                                float v = vEdgeMatrix[moffset+col];
118
119                                                r = (rgb & 0xff0000) >> 16;
120                                                g = (rgb & 0x00ff00) >> 8;
121                                                b = rgb & 0x0000ff;
122                                                rh += (int)(h * r);
123                                                gh += (int)(h * g);
124                                                bh += (int)(h * b);
125                                                rv += (int)(v * r);
126                                                gv += (int)(v * g);
127                                                bv += (int)(v * b);
128                                        }
129                                }
130                                r = (int)(Math.sqrt(rh*rh + rv*rv) / 1.8);
131                                g = (int)(Math.sqrt(gh*gh + gv*gv) / 1.8);
132                                b = (int)(Math.sqrt(bh*bh + bv*bv) / 1.8);
133                                r = PixelUtils.clamp(r);
134                                g = PixelUtils.clamp(g);
135                                b = PixelUtils.clamp(b);
136                                outPixels[index++] = a | (r << 16) | (g << 8) | b;
137                        }
138
139                }
140                return outPixels;
141        }
142
143        public String toString() {
144                return "Edges/Detect Edges";
145        }
146}