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.math.Noise; 041import lucee.runtime.type.KeyImpl; 042import lucee.runtime.type.Struct; 043import lucee.runtime.type.util.CollectionUtil; 044 045/** 046 * A filter which distorts an image as if it were underwater. 047 */ 048public class SwimFilter extends TransformFilter implements DynFiltering { 049 050 private float scale = 32; 051 private float stretch = 1.0f; 052 private float angle = 0.0f; 053 private float amount = 1.0f; 054 private float turbulence = 1.0f; 055 private float time = 0.0f; 056 private float m00 = 1.0f; 057 private float m01 = 0.0f; 058 private float m10 = 0.0f; 059 private float m11 = 1.0f; 060 061 public SwimFilter() { 062 } 063 064 /** 065 * Set the amount of swim. 066 * @param amount the amount of swim 067 * @min-value 0 068 * @max-value 100+ 069 * @see #getAmount 070 */ 071 public void setAmount(float amount) { 072 this.amount = amount; 073 } 074 075 /** 076 * Get the amount of swim. 077 * @return the amount swim 078 * @see #setAmount 079 */ 080 public float getAmount() { 081 return amount; 082 } 083 084 /** 085 * Specifies the scale of the distortion. 086 * @param scale the scale of the distortion. 087 * @min-value 1 088 * @max-value 300+ 089 * @see #getScale 090 */ 091 public void setScale(float scale) { 092 this.scale = scale; 093 } 094 095 /** 096 * Returns the scale of the distortion. 097 * @return the scale of the distortion. 098 * @see #setScale 099 */ 100 public float getScale() { 101 return scale; 102 } 103 104 /** 105 * Specifies the stretch factor of the distortion. 106 * @param stretch the stretch factor of the distortion. 107 * @min-value 1 108 * @max-value 50+ 109 * @see #getStretch 110 */ 111 public void setStretch(float stretch) { 112 this.stretch = stretch; 113 } 114 115 /** 116 * Returns the stretch factor of the distortion. 117 * @return the stretch factor of the distortion. 118 * @see #setStretch 119 */ 120 public float getStretch() { 121 return stretch; 122 } 123 124 /** 125 * Specifies the angle of the effect. 126 * @param angle the angle of the effect. 127 * @angle 128 * @see #getAngle 129 */ 130 public void setAngle(float angle) { 131 this.angle = angle; 132 float cos = (float)Math.cos(angle); 133 float sin = (float)Math.sin(angle); 134 m00 = cos; 135 m01 = sin; 136 m10 = -sin; 137 m11 = cos; 138 } 139 140 /** 141 * Returns the angle of the effect. 142 * @return the angle of the effect. 143 * @see #setAngle 144 */ 145 public float getAngle() { 146 return angle; 147 } 148 149 /** 150 * Specifies the turbulence of the texture. 151 * @param turbulence the turbulence of the texture. 152 * @min-value 0 153 * @max-value 1 154 * @see #getTurbulence 155 */ 156 public void setTurbulence(float turbulence) { 157 this.turbulence = turbulence; 158 } 159 160 /** 161 * Returns the turbulence of the effect. 162 * @return the turbulence of the effect. 163 * @see #setTurbulence 164 */ 165 public float getTurbulence() { 166 return turbulence; 167 } 168 169 /** 170 * Specifies the time. Use this to animate the effect. 171 * @param time the time. 172 * @angle 173 * @see #getTime 174 */ 175 public void setTime(float time) { 176 this.time = time; 177 } 178 179 /** 180 * Returns the time. 181 * @return the time. 182 * @see #setTime 183 */ 184 public float getTime() { 185 return time; 186 } 187 188 protected void transformInverse(int x, int y, float[] out) { 189 float nx = m00*x + m01*y; 190 float ny = m10*x + m11*y; 191 nx /= scale; 192 ny /= scale * stretch; 193 194 if ( turbulence == 1.0f ) { 195 out[0] = x + amount * Noise.noise3(nx+0.5f, ny, time); 196 out[1] = y + amount * Noise.noise3(nx, ny+0.5f, time); 197 } else { 198 out[0] = x + amount * Noise.turbulence3(nx+0.5f, ny, turbulence, time); 199 out[1] = y + amount * Noise.turbulence3(nx, ny+0.5f, turbulence, time); 200 } 201 } 202 203 public String toString() { 204 return "Distort/Swim..."; 205 } 206 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=null;//ImageUtil.createBufferedImage(src); 207 Object o; 208 if((o=parameters.removeEL(KeyImpl.init("Amount")))!=null)setAmount(ImageFilterUtil.toFloatValue(o,"Amount")); 209 if((o=parameters.removeEL(KeyImpl.init("Turbulence")))!=null)setTurbulence(ImageFilterUtil.toFloatValue(o,"Turbulence")); 210 if((o=parameters.removeEL(KeyImpl.init("Stretch")))!=null)setStretch(ImageFilterUtil.toFloatValue(o,"Stretch")); 211 if((o=parameters.removeEL(KeyImpl.init("Angle")))!=null)setAngle(ImageFilterUtil.toFloatValue(o,"Angle")); 212 if((o=parameters.removeEL(KeyImpl.init("Time")))!=null)setTime(ImageFilterUtil.toFloatValue(o,"Time")); 213 if((o=parameters.removeEL(KeyImpl.init("Scale")))!=null)setScale(ImageFilterUtil.toFloatValue(o,"Scale")); 214 if((o=parameters.removeEL(KeyImpl.init("EdgeAction")))!=null)setEdgeAction(ImageFilterUtil.toString(o,"EdgeAction")); 215 if((o=parameters.removeEL(KeyImpl.init("Interpolation")))!=null)setInterpolation(ImageFilterUtil.toString(o,"Interpolation")); 216 217 // check for arguments not supported 218 if(parameters.size()>0) { 219 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 [Amount, Turbulence, Stretch, Angle, Time, Scale, EdgeAction, Interpolation]"); 220 } 221 222 return filter(src, dst); 223 } 224}