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.Color; 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.Struct; 026 import railo.runtime.type.util.CollectionUtil; 027 028 /** 029 * A filter which produces a rubber-stamp type of effect by performing a thresholded blur. 030 */ 031 public class StampFilter extends PointFilter implements DynFiltering { 032 033 private float threshold; 034 private float softness = 0; 035 private float radius = 5; 036 private float lowerThreshold3; 037 private float upperThreshold3; 038 private int white = 0xffffffff; 039 private int black = 0xff000000; 040 041 /** 042 * Construct a StampFilter. 043 */ 044 public StampFilter() { 045 this(0.5f); 046 } 047 048 /** 049 * Construct a StampFilter. 050 * @param threshold the threshold value 051 */ 052 public StampFilter( float threshold ) { 053 setThreshold( threshold ); 054 } 055 056 /** 057 * Set the radius of the effect. 058 * @param radius the radius 059 * @min-value 0 060 * @see #getRadius 061 */ 062 public void setRadius(float radius) { 063 this.radius = radius; 064 } 065 066 /** 067 * Get the radius of the effect. 068 * @return the radius 069 * @see #setRadius 070 */ 071 public float getRadius() { 072 return radius; 073 } 074 075 /** 076 * Set the threshold value. 077 * @param threshold the threshold value 078 * @see #getThreshold 079 */ 080 public void setThreshold(float threshold) { 081 this.threshold = threshold; 082 } 083 084 /** 085 * Get the threshold value. 086 * @return the threshold value 087 * @see #setThreshold 088 */ 089 public float getThreshold() { 090 return threshold; 091 } 092 093 /** 094 * Set the softness of the effect in the range 0..1. 095 * @param softness the softness 096 * @min-value 0 097 * @max-value 1 098 * @see #getSoftness 099 */ 100 public void setSoftness(float softness) { 101 this.softness = softness; 102 } 103 104 /** 105 * Get the softness of the effect. 106 * @return the softness 107 * @see #setSoftness 108 */ 109 public float getSoftness() { 110 return softness; 111 } 112 113 /** 114 * Set the color to be used for pixels above the upper threshold. 115 * @param white the color 116 * @see #getWhite 117 */ 118 public void setWhite(Color white) { 119 this.white = white.getRGB(); 120 } 121 122 /** 123 * Get the color to be used for pixels above the upper threshold. 124 * @return the color 125 * @see #setWhite 126 */ 127 public int getWhite() { 128 return white; 129 } 130 131 /** 132 * Set the color to be used for pixels below the lower threshold. 133 * @param black the color 134 * @see #getBlack 135 */ 136 public void setBlack(Color black) { 137 this.black = black.getRGB(); 138 } 139 140 /** 141 * Set the color to be used for pixels below the lower threshold. 142 * @return the color 143 * @see #setBlack 144 */ 145 public int getBlack() { 146 return black; 147 } 148 149 public BufferedImage filter( BufferedImage src, BufferedImage dst ) { 150 dst = new GaussianFilter( (int)radius ).filter( src, (BufferedImage)null ); 151 lowerThreshold3 = 255*3*(threshold - softness*0.5f); 152 upperThreshold3 = 255*3*(threshold + softness*0.5f); 153 return super.filter(dst, dst); 154 } 155 156 public int filterRGB(int x, int y, int rgb) { 157 //int a = rgb & 0xff000000; 158 int r = (rgb >> 16) & 0xff; 159 int g = (rgb >> 8) & 0xff; 160 int b = rgb & 0xff; 161 int l = r + g + b; 162 float f = ImageMath.smoothStep(lowerThreshold3, upperThreshold3, l); 163 return ImageMath.mixColors(f, black, white); 164 } 165 166 public String toString() { 167 return "Stylize/Stamp..."; 168 } 169 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src); 170 Object o; 171 if((o=parameters.removeEL(KeyImpl.init("Radius")))!=null)setRadius(ImageFilterUtil.toFloatValue(o,"Radius")); 172 if((o=parameters.removeEL(KeyImpl.init("Softness")))!=null)setSoftness(ImageFilterUtil.toFloatValue(o,"Softness")); 173 if((o=parameters.removeEL(KeyImpl.init("White")))!=null)setWhite(ImageFilterUtil.toColor(o,"White")); 174 if((o=parameters.removeEL(KeyImpl.init("Black")))!=null)setBlack(ImageFilterUtil.toColor(o,"Black")); 175 if((o=parameters.removeEL(KeyImpl.init("Threshold")))!=null)setThreshold(ImageFilterUtil.toFloatValue(o,"Threshold")); 176 if((o=parameters.removeEL(KeyImpl.init("Dimensions")))!=null){ 177 int[] dim=ImageFilterUtil.toDimensions(o,"Dimensions"); 178 setDimensions(dim[0],dim[1]); 179 } 180 181 // check for arguments not supported 182 if(parameters.size()>0) { 183 throw new FunctionException(ThreadLocalPageContext.get(), "ImageFilter", 3, "parameters", "the parameter"+(parameters.size()>1?"s":"")+" ["+CollectionUtil.getKeyList(parameters,", ")+"] "+(parameters.size()>1?"are":"is")+" not allowed, only the following parameters are supported [Radius, Softness, White, Black, Threshold, Dimensions]"); 184 } 185 186 return filter(src, dst); 187 } 188 }