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.Function2D; 042import lucee.runtime.img.math.Noise; 043import lucee.runtime.type.KeyImpl; 044import lucee.runtime.type.Struct; 045import lucee.runtime.type.util.CollectionUtil; 046 047public class TextureFilter extends PointFilter implements DynFiltering { 048 049 private float scale = 32; 050 private float stretch = 1.0f; 051 private float angle = 0.0f; 052 public float amount = 1.0f; 053 public float turbulence = 1.0f; 054 public float gain = 0.5f; 055 public float bias = 0.5f; 056 public int operation; 057 private float m00 = 1.0f; 058 private float m01 = 0.0f; 059 private float m10 = 0.0f; 060 private float m11 = 1.0f; 061 private Colormap colormap = new Gradient(); 062 private Function2D function = new Noise(); 063 064 public TextureFilter() { 065 } 066 067 /** 068 * Set the amount of texture. 069 * @param amount the amount 070 * @min-value 0 071 * @max-value 1 072 * @see #getAmount 073 */ 074 public void setAmount(float amount) { 075 this.amount = amount; 076 } 077 078 /** 079 * Get the amount of texture. 080 * @return the amount 081 * @see #setAmount 082 */ 083 public float getAmount() { 084 return amount; 085 } 086 087 public void setFunction(Function2D function) { 088 this.function = function; 089 } 090 091 public Function2D getFunction() { 092 return function; 093 } 094 095 public void setOperation(int operation) { 096 this.operation = operation; 097 } 098 099 public int getOperation() { 100 return operation; 101 } 102 103 /** 104 * Specifies the scale of the texture. 105 * @param scale the scale of the texture. 106 * @min-value 1 107 * @max-value 300+ 108 * @see #getScale 109 */ 110 public void setScale(float scale) { 111 this.scale = scale; 112 } 113 114 /** 115 * Returns the scale of the texture. 116 * @return the scale of the texture. 117 * @see #setScale 118 */ 119 public float getScale() { 120 return scale; 121 } 122 123 /** 124 * Specifies the stretch factor of the texture. 125 * @param stretch the stretch factor of the texture. 126 * @min-value 1 127 * @max-value 50+ 128 * @see #getStretch 129 */ 130 public void setStretch(float stretch) { 131 this.stretch = stretch; 132 } 133 134 /** 135 * Returns the stretch factor of the texture. 136 * @return the stretch factor of the texture. 137 * @see #setStretch 138 */ 139 public float getStretch() { 140 return stretch; 141 } 142 143 /** 144 * Specifies the angle of the texture. 145 * @param angle the angle of the texture. 146 * @angle 147 * @see #getAngle 148 */ 149 public void setAngle(float angle) { 150 this.angle = angle; 151 float cos = (float)Math.cos(angle); 152 float sin = (float)Math.sin(angle); 153 m00 = cos; 154 m01 = sin; 155 m10 = -sin; 156 m11 = cos; 157 } 158 159 /** 160 * Returns the angle of the texture. 161 * @return the angle of the texture. 162 * @see #setAngle 163 */ 164 public float getAngle() { 165 return angle; 166 } 167 168 /** 169 * Specifies the turbulence of the texture. 170 * @param turbulence the turbulence of the texture. 171 * @min-value 0 172 * @max-value 1 173 * @see #getTurbulence 174 */ 175 public void setTurbulence(float turbulence) { 176 this.turbulence = turbulence; 177 } 178 179 /** 180 * Returns the turbulence of the texture. 181 * @return the turbulence of the texture. 182 * @see #setTurbulence 183 */ 184 public float getTurbulence() { 185 return turbulence; 186 } 187 188 /** 189 * Set the colormap to be used for the filter. 190 * @param colormap the colormap 191 * @see #getColormap 192 */ 193 public void setColormap(Colormap colormap) { 194 this.colormap = colormap; 195 } 196 197 /** 198 * Get the colormap to be used for the filter. 199 * @return the colormap 200 * @see #setColormap 201 */ 202 public Colormap getColormap() { 203 return colormap; 204 } 205 206 public int filterRGB(int x, int y, int rgb) { 207 float nx = m00*x + m01*y; 208 float ny = m10*x + m11*y; 209 nx /= scale; 210 ny /= scale * stretch; 211 float f = turbulence == 1.0 ? Noise.noise2(nx, ny) : Noise.turbulence2(nx, ny, turbulence); 212 f = (f * 0.5f) + 0.5f; 213 f = ImageMath.gain(f, gain); 214 f = ImageMath.bias(f, bias); 215 f *= amount; 216 int a = rgb & 0xff000000; 217 int v; 218 if (colormap != null) 219 v = colormap.getColor(f); 220 else { 221 v = PixelUtils.clamp((int)(f*255)); 222 int r = v << 16; 223 int g = v << 8; 224 int b = v; 225 v = a|r|g|b; 226 } 227 if (operation != PixelUtils.REPLACE) 228 v = PixelUtils.combinePixels(rgb, v, operation); 229 return v; 230 } 231 232 public String toString() { 233 return "Texture/Noise..."; 234 } 235 236 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src); 237 Object o; 238 if((o=parameters.removeEL(KeyImpl.init("Colormap")))!=null)setColormap(ImageFilterUtil.toColormap(o,"Colormap")); 239 if((o=parameters.removeEL(KeyImpl.init("Amount")))!=null)setAmount(ImageFilterUtil.toFloatValue(o,"Amount")); 240 if((o=parameters.removeEL(KeyImpl.init("Turbulence")))!=null)setTurbulence(ImageFilterUtil.toFloatValue(o,"Turbulence")); 241 if((o=parameters.removeEL(KeyImpl.init("Stretch")))!=null)setStretch(ImageFilterUtil.toFloatValue(o,"Stretch")); 242 if((o=parameters.removeEL(KeyImpl.init("Angle")))!=null)setAngle(ImageFilterUtil.toFloatValue(o,"Angle")); 243 if((o=parameters.removeEL(KeyImpl.init("Operation")))!=null)setOperation(ImageFilterUtil.toIntValue(o,"Operation")); 244 if((o=parameters.removeEL(KeyImpl.init("Function")))!=null)setFunction(ImageFilterUtil.toFunction2D(o,"Function")); 245 if((o=parameters.removeEL(KeyImpl.init("Scale")))!=null)setScale(ImageFilterUtil.toFloatValue(o,"Scale")); 246 if((o=parameters.removeEL(KeyImpl.init("Dimensions")))!=null){ 247 int[] dim=ImageFilterUtil.toDimensions(o,"Dimensions"); 248 setDimensions(dim[0],dim[1]); 249 } 250 251 // check for arguments not supported 252 if(parameters.size()>0) { 253 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, Amount, Turbulence, Stretch, Angle, Operation, Function, Scale, Dimensions]"); 254 } 255 256 return filter(src, dst); 257 } 258}