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.image.BufferedImage; 018 019 import railo.runtime.engine.ThreadLocalPageContext; 020 import railo.runtime.exp.FunctionException; 021 import railo.runtime.exp.PageException; 022 import railo.runtime.img.ImageUtil; 023 import railo.runtime.img.math.Noise; 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 simulated wood texture. This is a bit of a hack, but might be usefult to some people. 030 */ 031 public class WoodFilter extends PointFilter implements DynFiltering { 032 033 private float scale = 200; 034 private float stretch = 10.0f; 035 private float angle = (float)Math.PI/2; 036 private float rings = 0.5f; 037 private float turbulence = 0.0f; 038 private float fibres = 0.5f; 039 private float gain = 0.8f; 040 private float m00 = 1.0f; 041 private float m01 = 0.0f; 042 private float m10 = 0.0f; 043 private float m11 = 1.0f; 044 private Colormap colormap = new LinearColormap( 0xffe5c494, 0xff987b51 ); 045 046 /** 047 * Construct a WoodFilter. 048 */ 049 public WoodFilter() { 050 } 051 052 /** 053 * Specifies the rings value. 054 * @param rings the rings value. 055 * @min-value 0 056 * @max-value 1 057 * @see #getRings 058 */ 059 public void setRings(float rings) { 060 this.rings = rings; 061 } 062 063 /** 064 * Returns the rings value. 065 * @return the rings value. 066 * @see #setRings 067 */ 068 public float getRings() { 069 return rings; 070 } 071 072 /** 073 * Specifies the scale of the texture. 074 * @param scale the scale of the texture. 075 * @min-value 1 076 * @max-value 300+ 077 * @see #getScale 078 */ 079 public void setScale(float scale) { 080 this.scale = scale; 081 } 082 083 /** 084 * Returns the scale of the texture. 085 * @return the scale of the texture. 086 * @see #setScale 087 */ 088 public float getScale() { 089 return scale; 090 } 091 092 /** 093 * Specifies the stretch factor of the texture. 094 * @param stretch the stretch factor of the texture. 095 * @min-value 1 096 * @max-value 50+ 097 * @see #getStretch 098 */ 099 public void setStretch(float stretch) { 100 this.stretch = stretch; 101 } 102 103 /** 104 * Returns the stretch factor of the texture. 105 * @return the stretch factor of the texture. 106 * @see #setStretch 107 */ 108 public float getStretch() { 109 return stretch; 110 } 111 112 /** 113 * Specifies the angle of the texture. 114 * @param angle the angle of the texture. 115 * @angle 116 * @see #getAngle 117 */ 118 public void setAngle(float angle) { 119 this.angle = angle; 120 float cos = (float)Math.cos(angle); 121 float sin = (float)Math.sin(angle); 122 m00 = cos; 123 m01 = sin; 124 m10 = -sin; 125 m11 = cos; 126 } 127 128 /** 129 * Returns the angle of the texture. 130 * @return the angle of the texture. 131 * @see #setAngle 132 */ 133 public float getAngle() { 134 return angle; 135 } 136 137 /** 138 * Specifies the turbulence of the texture. 139 * @param turbulence the turbulence of the texture. 140 * @min-value 0 141 * @max-value 1 142 * @see #getTurbulence 143 */ 144 public void setTurbulence(float turbulence) { 145 this.turbulence = turbulence; 146 } 147 148 /** 149 * Returns the turbulence of the texture. 150 * @return the turbulence of the texture. 151 * @see #setTurbulence 152 */ 153 public float getTurbulence() { 154 return turbulence; 155 } 156 157 /** 158 * Specifies the amount of fibres in the texture. 159 * @param fibres the amount of fibres in the texture. 160 * @min-value 0 161 * @max-value 1 162 * @see #getFibres 163 */ 164 public void setFibres(float fibres) { 165 this.fibres = fibres; 166 } 167 168 /** 169 * Returns the amount of fibres in the texture. 170 * @return the amount of fibres in the texture. 171 * @see #setFibres 172 */ 173 public float getFibres() { 174 return fibres; 175 } 176 177 /** 178 * Specifies the gain of the texture. 179 * @param gain the gain of the texture. 180 * @min-value 0 181 * @max-value 1 182 * @see #getGain 183 */ 184 public void setGain(float gain) { 185 this.gain = gain; 186 } 187 188 /** 189 * Returns the gain of the texture. 190 * @return the gain of the texture. 191 * @see #setGain 192 */ 193 public float getGain() { 194 return gain; 195 } 196 197 /** 198 * Set the colormap to be used for the filter. 199 * @param colormap the colormap 200 * @see #getColormap 201 */ 202 public void setColormap(Colormap colormap) { 203 this.colormap = colormap; 204 } 205 206 /** 207 * Get the colormap to be used for the filter. 208 * @return the colormap 209 * @see #setColormap 210 */ 211 public Colormap getColormap() { 212 return colormap; 213 } 214 215 public int filterRGB(int x, int y, int rgb) { 216 float nx = m00*x + m01*y; 217 float ny = m10*x + m11*y; 218 nx /= scale; 219 ny /= scale * stretch; 220 float f = Noise.noise2(nx, ny); 221 f += 0.1f*turbulence * Noise.noise2(nx*0.05f, ny*20); 222 f = (f * 0.5f) + 0.5f; 223 224 f *= rings*50; 225 f = f-(int)f; 226 f *= 1-ImageMath.smoothStep(gain, 1.0f, f); 227 228 f += fibres*Noise.noise2(nx*scale, ny*50); 229 230 int a = rgb & 0xff000000; 231 int v; 232 if (colormap != null) 233 v = colormap.getColor(f); 234 else { 235 v = PixelUtils.clamp((int)(f*255)); 236 int r = v << 16; 237 int g = v << 8; 238 int b = v; 239 v = a|r|g|b; 240 } 241 242 return v; 243 } 244 245 public String toString() { 246 return "Texture/Wood..."; 247 } 248 249 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src); 250 Object o; 251 if((o=parameters.removeEL(KeyImpl.init("Colormap")))!=null)setColormap(ImageFilterUtil.toColormap(o,"Colormap")); 252 if((o=parameters.removeEL(KeyImpl.init("Turbulence")))!=null)setTurbulence(ImageFilterUtil.toFloatValue(o,"Turbulence")); 253 if((o=parameters.removeEL(KeyImpl.init("Stretch")))!=null)setStretch(ImageFilterUtil.toFloatValue(o,"Stretch")); 254 if((o=parameters.removeEL(KeyImpl.init("Angle")))!=null)setAngle(ImageFilterUtil.toFloatValue(o,"Angle")); 255 if((o=parameters.removeEL(KeyImpl.init("Gain")))!=null)setGain(ImageFilterUtil.toFloatValue(o,"Gain")); 256 if((o=parameters.removeEL(KeyImpl.init("Rings")))!=null)setRings(ImageFilterUtil.toFloatValue(o,"Rings")); 257 if((o=parameters.removeEL(KeyImpl.init("Fibres")))!=null)setFibres(ImageFilterUtil.toFloatValue(o,"Fibres")); 258 if((o=parameters.removeEL(KeyImpl.init("Scale")))!=null)setScale(ImageFilterUtil.toFloatValue(o,"Scale")); 259 if((o=parameters.removeEL(KeyImpl.init("Dimensions")))!=null){ 260 int[] dim=ImageFilterUtil.toDimensions(o,"Dimensions"); 261 setDimensions(dim[0],dim[1]); 262 } 263 264 // check for arguments not supported 265 if(parameters.size()>0) { 266 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 [Colormap, Turbulence, Stretch, Angle, Gain, Rings, Fibres, Scale, Dimensions]"); 267 } 268 269 return filter(src, dst); 270 } 271 }