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.*;
021import com.jhlabs.composite.*;
022
023/**
024 * Edge detection via the Laplacian operator.
025 * @author Jerry Huxtable
026 */
027public class LaplaceFilter extends AbstractBufferedImageOp {
028
029    private void brightness( int[] row ) {
030        for ( int i = 0; i < row.length; i++ ) {
031            int rgb = row[i];
032            int r = rgb >> 16 & 0xff;
033            int g = rgb >> 8 & 0xff;
034            int b = rgb & 0xff;
035            row[i] = (r + g + b) / 3;
036        }
037    }
038
039    public BufferedImage filter( BufferedImage src, BufferedImage dst ) {
040        int width = src.getWidth();
041        int height = src.getHeight();
042
043        if ( dst == null )
044            dst = createCompatibleDestImage( src, null );
045
046        int[] row1 = null;
047        int[] row2 = null;
048        int[] row3 = null;
049        int[] pixels = new int[width];
050        row1 = getRGB( src, 0, 0, width, 1, row1 );
051        row2 = getRGB( src, 0, 0, width, 1, row2 );
052        brightness( row1 );
053        brightness( row2 );
054        for ( int y = 0; y < height; y++ ) {
055            if ( y < height-1) {
056                row3 = getRGB( src, 0, y+1, width, 1, row3 );
057                brightness( row3 );
058            }
059            pixels[0] = pixels[width-1] = 0xff000000;//FIXME
060            for ( int x = 1; x < width-1; x++ ) {
061                int l1 = row2[x-1];
062                int l2 = row1[x];
063                int l3 = row3[x];
064                int l4 = row2[x+1];
065
066                int l = row2[x];
067                int max = Math.max( Math.max( l1, l2 ), Math.max( l3, l4 ) );
068                int min = Math.min( Math.min( l1, l2 ), Math.min( l3, l4 ) );
069
070                int gradient = (int)(0.5f * Math.max( (max - l), (l - min) ));
071
072                int r = ((row1[x-1] + row1[x] + row1[x+1] +
073                    row2[x-1] - (8 * row2[x]) + row2[x+1] +
074                    row3[x-1] + row3[x] + row3[x+1]) > 0) ?
075                        gradient : (128 + gradient);
076                pixels[x] = r;
077            }
078            setRGB( dst, 0, y, width, 1, pixels );
079            int[] t = row1; row1 = row2; row2 = row3; row3 = t;
080        }
081
082        row1 = getRGB( dst, 0, 0, width, 1, row1 );
083        row2 = getRGB( dst, 0, 0, width, 1, row2 );
084        for ( int y = 0; y < height; y++ ) {
085            if ( y < height-1) {
086                row3 = getRGB( dst, 0, y+1, width, 1, row3 );
087            }
088            pixels[0] = pixels[width-1] = 0xff000000;//FIXME
089            for ( int x = 1; x < width-1; x++ ) {
090                int r = row2[x];
091                r = (((r <= 128) &&
092                      ((row1[x - 1] > 128) ||
093                       (row1[x] > 128)         ||
094                       (row1[x + 1] > 128) ||
095                       (row2[x - 1] > 128) ||
096                       (row2[x + 1] > 128) ||
097                       (row3[x - 1] > 128) ||
098                       (row3[x] > 128)         ||
099                       (row3[x + 1] > 128))) ?
100                     ((r >= 128) ? (r - 128) : r) : 0);
101
102                pixels[x] = 0xff000000 | (r << 16) | (r << 8) | r;
103            }
104            setRGB( dst, 0, y, width, 1, pixels );
105            int[] t = row1; row1 = row2; row2 = row3; row3 = t;
106        }
107
108        return dst;
109    }
110
111        public String toString() {
112                return "Edges/Laplace...";
113        }
114}