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.KeyImpl; 025 import railo.runtime.type.List; 026 import railo.runtime.type.Struct; 027 028 /** 029 * Given a binary image, this filter performs binary dilation, setting all added pixels to the given 'new' color. 030 */ 031 public class DilateFilter extends BinaryFilter implements DynFiltering { 032 033 private int threshold = 2; 034 035 public DilateFilter() { 036 } 037 038 /** 039 * Set the threshold - the number of neighbouring pixels for dilation to occur. 040 * @param threshold the new threshold 041 * @see #getThreshold 042 */ 043 public void setThreshold(int threshold) { 044 this.threshold = threshold; 045 } 046 047 /** 048 * Return the threshold - the number of neighbouring pixels for dilation to occur. 049 * @return the current threshold 050 * @see #setThreshold 051 */ 052 public int getThreshold() { 053 return threshold; 054 } 055 056 protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { 057 int[] outPixels = new int[width * height]; 058 059 for (int i = 0; i < iterations; i++) { 060 int index = 0; 061 062 if (i > 0) { 063 int[] t = inPixels; 064 inPixels = outPixels; 065 outPixels = t; 066 } 067 for (int y = 0; y < height; y++) { 068 for (int x = 0; x < width; x++) { 069 int pixel = inPixels[y*width+x]; 070 if (!blackFunction.isBlack(pixel)) { 071 int neighbours = 0; 072 073 for (int dy = -1; dy <= 1; dy++) { 074 int iy = y+dy; 075 int ioffset; 076 if (0 <= iy && iy < height) { 077 ioffset = iy*width; 078 for (int dx = -1; dx <= 1; dx++) { 079 int ix = x+dx; 080 if (!(dy == 0 && dx == 0) && 0 <= ix && ix < width) { 081 int rgb = inPixels[ioffset+ix]; 082 if (blackFunction.isBlack(rgb)) 083 neighbours++; 084 } 085 } 086 } 087 } 088 089 if (neighbours >= threshold) { 090 if (colormap != null) 091 pixel = colormap.getColor((float)i/iterations); 092 else 093 pixel = newColor; 094 } 095 } 096 outPixels[index++] = pixel; 097 } 098 } 099 } 100 return outPixels; 101 } 102 103 public String toString() { 104 return "Binary/Dilate..."; 105 } 106 107 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src); 108 Object o; 109 if((o=parameters.removeEL(KeyImpl.init("Threshold")))!=null)setThreshold(ImageFilterUtil.toIntValue(o,"Threshold")); 110 if((o=parameters.removeEL(KeyImpl.init("Iterations")))!=null)setIterations(ImageFilterUtil.toIntValue(o,"Iterations")); 111 if((o=parameters.removeEL(KeyImpl.init("Colormap")))!=null)setColormap(ImageFilterUtil.toColormap(o,"Colormap")); 112 if((o=parameters.removeEL(KeyImpl.init("NewColor")))!=null)setNewColor(ImageFilterUtil.toColorRGB(o,"NewColor")); 113 114 // check for arguments not supported 115 if(parameters.size()>0) { 116 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 [Threshold, Iterations, Colormap, NewColor, BlackFunction]"); 117 } 118 119 return filter(src, dst); 120 } 121 } 122