001/*******************************************************************************
002 * This software is provided as a supplement to the authors' textbooks on digital
003 *  image processing published by Springer-Verlag in various languages and editions.
004 * Permission to use and distribute this software is granted under the BSD 2-Clause 
005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 
006 * Copyright (c) 2006-2016 Wilhelm Burger, Mark J. Burge. All rights reserved. 
007 * Visit http://imagingbook.com for additional details.
008 *******************************************************************************/
009
010package imagingbook.lib.filters;
011
012import imagingbook.lib.image.ImageAccessor;
013
014
015/**
016 * Generic linear convolution filter implemented
017 * by extending the GenericFilter class.
018 */
019public class LinearFilter extends GenericFilter {
020        
021        private final float[][] kernel2d;
022        private final float[] rgb = { 0, 0, 0 };
023
024        private final int kernelWidth, kernelHeight;    // width/height of the kernel
025        private final int kernelCtrX, kernelCtrY;       // center coordinates of the kernel
026        
027        public LinearFilter(float[][] kernel2d) {
028                this.kernel2d = kernel2d;
029                this.kernelWidth = kernel2d.length;
030                this.kernelHeight = kernel2d[0].length;
031                this.kernelCtrX = kernelWidth / 2;
032                this.kernelCtrY = kernelHeight / 2;
033        }
034        
035        // --------------------------------------------------------------
036        
037
038        public float filterPixel(ImageAccessor.Scalar ia, int u, int v) {
039                float sum = 0;
040                for (int j = 0; j < kernelHeight; j++) {
041                        int vj = v + j - kernelCtrY;
042                        for (int i = 0; i < kernelWidth; i++) {
043                                int ui = u + i - kernelCtrX;
044                                sum = sum + ia.getVal(ui, vj) * kernel2d[i][j];
045                        }
046                }
047                return sum;
048        }
049        
050        public float[] filterPixel(ImageAccessor.Rgb ia, int u, int v) {
051                float sumR = 0; // sum of weighted red
052                float sumG = 0; // sum of weighted green
053                float sumB = 0; // sum of weighted blue
054                for (int j = 0; j < kernelHeight; j++) {
055                        int vj = v + j - kernelCtrY;
056                        for (int i = 0; i < kernelWidth; i++) {
057                                int ui = u + i - kernelCtrX;
058                                float[] val = ia.getPix(ui, vj);
059                                float w = kernel2d[i][j];
060                                sumR = sumR + val[0] * w;
061                                sumG = sumG + val[1] * w;
062                                sumB = sumB + val[2] * w;
063                        }
064                }
065                rgb[0] = sumR;
066                rgb[1] = sumG;
067                rgb[2] = sumB;
068                return rgb;
069        }
070
071        // --------------------------------------------------------------
072
073//      @Deprecated     // return a string instead
074//      public void listKernel() {
075//              for (int j = 0; j < kernelHeight; j++) {
076//                      StringBuilder sb = new StringBuilder();
077//                      Formatter fm = new Formatter(sb, Locale.US);
078//                      for (int i = 0; i < kernelWidth; i++) {
079//                              fm.format(" %.5f | ", kernel2d[i][j]);
080//                      }
081//                      fm.format("\n");
082//                      IJ.log(fm.toString());
083//                      fm.close();
084//              }
085//      }
086}