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