001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019/* 020* 021 022Licensed under the Apache License, Version 2.0 (the "License"); 023you may not use this file except in compliance with the License. 024You may obtain a copy of the License at 025 026 http://www.apache.org/licenses/LICENSE-2.0 027 028Unless required by applicable law or agreed to in writing, software 029distributed under the License is distributed on an "AS IS" BASIS, 030WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 031See the License for the specific language governing permissions and 032limitations under the License. 033*/ 034 035package lucee.runtime.img.filter;import java.awt.image.BufferedImage; 036 037import lucee.runtime.engine.ThreadLocalPageContext; 038import lucee.runtime.exp.FunctionException; 039import lucee.runtime.exp.PageException; 040import lucee.runtime.img.ImageUtil; 041import lucee.runtime.img.math.Noise; 042import lucee.runtime.type.KeyImpl; 043import lucee.runtime.type.Struct; 044import lucee.runtime.type.util.CollectionUtil; 045 046/** 047 * A filter which produces a simulated wood texture. This is a bit of a hack, but might be usefult to some people. 048 */ 049public class WoodFilter extends PointFilter implements DynFiltering { 050 051 private float scale = 200; 052 private float stretch = 10.0f; 053 private float angle = (float)Math.PI/2; 054 private float rings = 0.5f; 055 private float turbulence = 0.0f; 056 private float fibres = 0.5f; 057 private float gain = 0.8f; 058 private float m00 = 1.0f; 059 private float m01 = 0.0f; 060 private float m10 = 0.0f; 061 private float m11 = 1.0f; 062 private Colormap colormap = new LinearColormap( 0xffe5c494, 0xff987b51 ); 063 064 /** 065 * Construct a WoodFilter. 066 */ 067 public WoodFilter() { 068 } 069 070 /** 071 * Specifies the rings value. 072 * @param rings the rings value. 073 * @min-value 0 074 * @max-value 1 075 * @see #getRings 076 */ 077 public void setRings(float rings) { 078 this.rings = rings; 079 } 080 081 /** 082 * Returns the rings value. 083 * @return the rings value. 084 * @see #setRings 085 */ 086 public float getRings() { 087 return rings; 088 } 089 090 /** 091 * Specifies the scale of the texture. 092 * @param scale the scale of the texture. 093 * @min-value 1 094 * @max-value 300+ 095 * @see #getScale 096 */ 097 public void setScale(float scale) { 098 this.scale = scale; 099 } 100 101 /** 102 * Returns the scale of the texture. 103 * @return the scale of the texture. 104 * @see #setScale 105 */ 106 public float getScale() { 107 return scale; 108 } 109 110 /** 111 * Specifies the stretch factor of the texture. 112 * @param stretch the stretch factor of the texture. 113 * @min-value 1 114 * @max-value 50+ 115 * @see #getStretch 116 */ 117 public void setStretch(float stretch) { 118 this.stretch = stretch; 119 } 120 121 /** 122 * Returns the stretch factor of the texture. 123 * @return the stretch factor of the texture. 124 * @see #setStretch 125 */ 126 public float getStretch() { 127 return stretch; 128 } 129 130 /** 131 * Specifies the angle of the texture. 132 * @param angle the angle of the texture. 133 * @angle 134 * @see #getAngle 135 */ 136 public void setAngle(float angle) { 137 this.angle = angle; 138 float cos = (float)Math.cos(angle); 139 float sin = (float)Math.sin(angle); 140 m00 = cos; 141 m01 = sin; 142 m10 = -sin; 143 m11 = cos; 144 } 145 146 /** 147 * Returns the angle of the texture. 148 * @return the angle of the texture. 149 * @see #setAngle 150 */ 151 public float getAngle() { 152 return angle; 153 } 154 155 /** 156 * Specifies the turbulence of the texture. 157 * @param turbulence the turbulence of the texture. 158 * @min-value 0 159 * @max-value 1 160 * @see #getTurbulence 161 */ 162 public void setTurbulence(float turbulence) { 163 this.turbulence = turbulence; 164 } 165 166 /** 167 * Returns the turbulence of the texture. 168 * @return the turbulence of the texture. 169 * @see #setTurbulence 170 */ 171 public float getTurbulence() { 172 return turbulence; 173 } 174 175 /** 176 * Specifies the amount of fibres in the texture. 177 * @param fibres the amount of fibres in the texture. 178 * @min-value 0 179 * @max-value 1 180 * @see #getFibres 181 */ 182 public void setFibres(float fibres) { 183 this.fibres = fibres; 184 } 185 186 /** 187 * Returns the amount of fibres in the texture. 188 * @return the amount of fibres in the texture. 189 * @see #setFibres 190 */ 191 public float getFibres() { 192 return fibres; 193 } 194 195 /** 196 * Specifies the gain of the texture. 197 * @param gain the gain of the texture. 198 * @min-value 0 199 * @max-value 1 200 * @see #getGain 201 */ 202 public void setGain(float gain) { 203 this.gain = gain; 204 } 205 206 /** 207 * Returns the gain of the texture. 208 * @return the gain of the texture. 209 * @see #setGain 210 */ 211 public float getGain() { 212 return gain; 213 } 214 215 /** 216 * Set the colormap to be used for the filter. 217 * @param colormap the colormap 218 * @see #getColormap 219 */ 220 public void setColormap(Colormap colormap) { 221 this.colormap = colormap; 222 } 223 224 /** 225 * Get the colormap to be used for the filter. 226 * @return the colormap 227 * @see #setColormap 228 */ 229 public Colormap getColormap() { 230 return colormap; 231 } 232 233 public int filterRGB(int x, int y, int rgb) { 234 float nx = m00*x + m01*y; 235 float ny = m10*x + m11*y; 236 nx /= scale; 237 ny /= scale * stretch; 238 float f = Noise.noise2(nx, ny); 239 f += 0.1f*turbulence * Noise.noise2(nx*0.05f, ny*20); 240 f = (f * 0.5f) + 0.5f; 241 242 f *= rings*50; 243 f = f-(int)f; 244 f *= 1-ImageMath.smoothStep(gain, 1.0f, f); 245 246 f += fibres*Noise.noise2(nx*scale, ny*50); 247 248 int a = rgb & 0xff000000; 249 int v; 250 if (colormap != null) 251 v = colormap.getColor(f); 252 else { 253 v = PixelUtils.clamp((int)(f*255)); 254 int r = v << 16; 255 int g = v << 8; 256 int b = v; 257 v = a|r|g|b; 258 } 259 260 return v; 261 } 262 263 public String toString() { 264 return "Texture/Wood..."; 265 } 266 267 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src); 268 Object o; 269 if((o=parameters.removeEL(KeyImpl.init("Colormap")))!=null)setColormap(ImageFilterUtil.toColormap(o,"Colormap")); 270 if((o=parameters.removeEL(KeyImpl.init("Turbulence")))!=null)setTurbulence(ImageFilterUtil.toFloatValue(o,"Turbulence")); 271 if((o=parameters.removeEL(KeyImpl.init("Stretch")))!=null)setStretch(ImageFilterUtil.toFloatValue(o,"Stretch")); 272 if((o=parameters.removeEL(KeyImpl.init("Angle")))!=null)setAngle(ImageFilterUtil.toFloatValue(o,"Angle")); 273 if((o=parameters.removeEL(KeyImpl.init("Gain")))!=null)setGain(ImageFilterUtil.toFloatValue(o,"Gain")); 274 if((o=parameters.removeEL(KeyImpl.init("Rings")))!=null)setRings(ImageFilterUtil.toFloatValue(o,"Rings")); 275 if((o=parameters.removeEL(KeyImpl.init("Fibres")))!=null)setFibres(ImageFilterUtil.toFloatValue(o,"Fibres")); 276 if((o=parameters.removeEL(KeyImpl.init("Scale")))!=null)setScale(ImageFilterUtil.toFloatValue(o,"Scale")); 277 if((o=parameters.removeEL(KeyImpl.init("Dimensions")))!=null){ 278 int[] dim=ImageFilterUtil.toDimensions(o,"Dimensions"); 279 setDimensions(dim[0],dim[1]); 280 } 281 282 // check for arguments not supported 283 if(parameters.size()>0) { 284 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]"); 285 } 286 287 return filter(src, dst); 288 } 289}