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 performs a 3x3 median operation. Useful for removing dust and noise. 024 */ 025public class MedianFilter extends WholeImageFilter { 026 027 public MedianFilter() { 028 } 029 030 private int median(int[] array) { 031 int max, maxIndex; 032 033 for (int i = 0; i < 4; i++) { 034 max = 0; 035 maxIndex = 0; 036 for (int j = 0; j < 9; j++) { 037 if (array[j] > max) { 038 max = array[j]; 039 maxIndex = j; 040 } 041 } 042 array[maxIndex] = 0; 043 } 044 max = 0; 045 for (int i = 0; i < 9; i++) { 046 if (array[i] > max) 047 max = array[i]; 048 } 049 return max; 050 } 051 052 private int rgbMedian(int[] r, int[] g, int[] b) { 053 int sum, index = 0, min = Integer.MAX_VALUE; 054 055 for (int i = 0; i < 9; i++) { 056 sum = 0; 057 for (int j = 0; j < 9; j++) { 058 sum += Math.abs(r[i]-r[j]); 059 sum += Math.abs(g[i]-g[j]); 060 sum += Math.abs(b[i]-b[j]); 061 } 062 if (sum < min) { 063 min = sum; 064 index = i; 065 } 066 } 067 return index; 068 } 069 070 protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { 071 int index = 0; 072 int[] argb = new int[9]; 073 int[] r = new int[9]; 074 int[] g = new int[9]; 075 int[] b = new int[9]; 076 int[] outPixels = new int[width * height]; 077 078 for (int y = 0; y < height; y++) { 079 for (int x = 0; x < width; x++) { 080 int k = 0; 081 for (int dy = -1; dy <= 1; dy++) { 082 int iy = y+dy; 083 if (0 <= iy && iy < height) { 084 int ioffset = iy*width; 085 for (int dx = -1; dx <= 1; dx++) { 086 int ix = x+dx; 087 if (0 <= ix && ix < width) { 088 int rgb = inPixels[ioffset+ix]; 089 argb[k] = rgb; 090 r[k] = (rgb >> 16) & 0xff; 091 g[k] = (rgb >> 8) & 0xff; 092 b[k] = rgb & 0xff; 093 k++; 094 } 095 } 096 } 097 } 098 while (k < 9) { 099 argb[k] = 0xff000000; 100 r[k] = g[k] = b[k] = 0; 101 k++; 102 } 103 outPixels[index++] = argb[rgbMedian(r, g, b)]; 104 } 105 } 106 return outPixels; 107 } 108 109 public String toString() { 110 return "Blur/Median"; 111 } 112 113} 114