001 /* 002 * 003 004 Licensed under the Apache License, Version 2.0 (the "License"); 005 you may not use this file except in compliance with the License. 006 You may obtain a copy of the License at 007 008 http://www.apache.org/licenses/LICENSE-2.0 009 010 Unless required by applicable law or agreed to in writing, software 011 distributed under the License is distributed on an "AS IS" BASIS, 012 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 See the License for the specific language governing permissions and 014 limitations under the License. 015 */ 016 017 package railo.runtime.img.filter;import java.awt.Rectangle; 018 import java.awt.image.BufferedImage; 019 020 import railo.runtime.engine.ThreadLocalPageContext; 021 import railo.runtime.exp.FunctionException; 022 import railo.runtime.exp.PageException; 023 import railo.runtime.img.ImageUtil; 024 import railo.runtime.type.List; 025 import railo.runtime.type.Struct; 026 027 /** 028 * A filter which removes noise from an image using a "pepper and salt" algorithm. 029 */ 030 public class DespeckleFilter extends WholeImageFilter implements DynFiltering { 031 032 public DespeckleFilter() { 033 } 034 035 private short pepperAndSalt( short c, short v1, short v2 ) { 036 if ( c < v1 ) 037 c++; 038 if ( c < v2 ) 039 c++; 040 if ( c > v1 ) 041 c--; 042 if ( c > v2 ) 043 c--; 044 return c; 045 } 046 047 protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { 048 int index = 0; 049 short[][] r = new short[3][width]; 050 short[][] g = new short[3][width]; 051 short[][] b = new short[3][width]; 052 int[] outPixels = new int[width * height]; 053 054 for (int x = 0; x < width; x++) { 055 int rgb = inPixels[x]; 056 r[1][x] = (short)((rgb >> 16) & 0xff); 057 g[1][x] = (short)((rgb >> 8) & 0xff); 058 b[1][x] = (short)(rgb & 0xff); 059 } 060 for (int y = 0; y < height; y++) { 061 boolean yIn = y > 0 && y < height-1; 062 int nextRowIndex = index+width; 063 if ( y < height-1) { 064 for (int x = 0; x < width; x++) { 065 int rgb = inPixels[nextRowIndex++]; 066 r[2][x] = (short)((rgb >> 16) & 0xff); 067 g[2][x] = (short)((rgb >> 8) & 0xff); 068 b[2][x] = (short)(rgb & 0xff); 069 } 070 } 071 for (int x = 0; x < width; x++) { 072 boolean xIn = x > 0 && x < width-1; 073 short or = r[1][x]; 074 short og = g[1][x]; 075 short ob = b[1][x]; 076 int w = x-1; 077 int e = x+1; 078 079 if ( yIn ) { 080 or = pepperAndSalt( or, r[0][x], r[2][x] ); 081 og = pepperAndSalt( og, g[0][x], g[2][x] ); 082 ob = pepperAndSalt( ob, b[0][x], b[2][x] ); 083 } 084 085 if ( xIn ) { 086 or = pepperAndSalt( or, r[1][w], r[1][e] ); 087 og = pepperAndSalt( og, g[1][w], g[1][e] ); 088 ob = pepperAndSalt( ob, b[1][w], b[1][e] ); 089 } 090 091 if ( yIn && xIn ) { 092 or = pepperAndSalt( or, r[0][w], r[2][e] ); 093 og = pepperAndSalt( og, g[0][w], g[2][e] ); 094 ob = pepperAndSalt( ob, b[0][w], b[2][e] ); 095 096 or = pepperAndSalt( or, r[2][w], r[0][e] ); 097 og = pepperAndSalt( og, g[2][w], g[0][e] ); 098 ob = pepperAndSalt( ob, b[2][w], b[0][e] ); 099 } 100 101 outPixels[index] = (inPixels[index] & 0xff000000) | (or << 16) | (og << 8) | ob; 102 index++; 103 } 104 short[] t; 105 t = r[0]; 106 r[0] = r[1]; 107 r[1] = r[2]; 108 r[2] = t; 109 t = g[0]; 110 g[0] = g[1]; 111 g[1] = g[2]; 112 g[2] = t; 113 t = b[0]; 114 b[0] = b[1]; 115 b[1] = b[2]; 116 b[2] = t; 117 } 118 119 return outPixels; 120 } 121 122 public String toString() { 123 return "Blur/Despeckle..."; 124 } 125 126 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src); 127 Object o; 128 129 // check for arguments not supported 130 if(parameters.size()>0) { 131 throw new FunctionException(ThreadLocalPageContext.get(), "ImageFilter", 3, "parameters", "the parameter"+(parameters.size()>1?"s":"")+" ["+List.arrayToList(parameters.keysAsString(),", ")+"] "+(parameters.size()>1?"are":"is")+" not allowed, only the following parameters are supported []"); 132 } 133 134 return filter(src, dst); 135 } 136 } 137