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 * This filter applies a marbling effect to an image, displacing pixels by random amounts. 047 */ 048public class MarbleFilter extends TransformFilter implements DynFiltering { 049 050 private float[] sinTable, cosTable; 051 private float xScale = 4; 052 private float yScale = 4; 053 private float amount = 1; 054 private float turbulence = 1; 055 056 public MarbleFilter() { 057 super(ConvolveFilter.CLAMP_EDGES); 058 } 059 060 /** 061 * Set the X scale of the effect. 062 * @param xScale the scale. 063 * @see #getXScale 064 */ 065 public void setXScale(float xScale) { 066 this.xScale = xScale; 067 } 068 069 /** 070 * Get the X scale of the effect. 071 * @return the scale. 072 * @see #setXScale 073 */ 074 public float getXScale() { 075 return xScale; 076 } 077 078 /** 079 * Set the Y scale of the effect. 080 * @param yScale the scale. 081 * @see #getYScale 082 */ 083 public void setYScale(float yScale) { 084 this.yScale = yScale; 085 } 086 087 /** 088 * Get the Y scale of the effect. 089 * @return the scale. 090 * @see #setYScale 091 */ 092 public float getYScale() { 093 return yScale; 094 } 095 096 /** 097 * Set the amount of effect. 098 * @param amount the amount 099 * @min-value 0 100 * @max-value 1 101 * @see #getAmount 102 */ 103 public void setAmount(float amount) { 104 this.amount = amount; 105 } 106 107 /** 108 * Get the amount of effect. 109 * @return the amount 110 * @see #setAmount 111 */ 112 public float getAmount() { 113 return amount; 114 } 115 116 /** 117 * Specifies the turbulence of the effect. 118 * @param turbulence the turbulence of the effect. 119 * @min-value 0 120 * @max-value 1 121 * @see #getTurbulence 122 */ 123 public void setTurbulence(float turbulence) { 124 this.turbulence = turbulence; 125 } 126 127 /** 128 * Returns the turbulence of the effect. 129 * @return the turbulence of the effect. 130 * @see #setTurbulence 131 */ 132 public float getTurbulence() { 133 return turbulence; 134 } 135 136 private void initialize() { 137 sinTable = new float[256]; 138 cosTable = new float[256]; 139 for (int i = 0; i < 256; i++) { 140 float angle = ImageMath.TWO_PI*i/256f*turbulence; 141 sinTable[i] = (float)(-yScale*Math.sin(angle)); 142 cosTable[i] = (float)(yScale*Math.cos(angle)); 143 } 144 } 145 146 private int displacementMap(int x, int y) { 147 return PixelUtils.clamp((int)(127 * (1+Noise.noise2(x / xScale, y / xScale)))); 148 } 149 150 protected void transformInverse(int x, int y, float[] out) { 151 int displacement = displacementMap(x, y); 152 out[0] = x + sinTable[displacement]; 153 out[1] = y + cosTable[displacement]; 154 } 155 156 public BufferedImage filter( BufferedImage src, BufferedImage dst ) { 157 initialize(); 158 return super.filter( src, dst ); 159 } 160 161 public String toString() { 162 return "Distort/Marble..."; 163 } 164 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=null;//ImageUtil.createBufferedImage(src); 165 Object o; 166 if((o=parameters.removeEL(KeyImpl.init("Amount")))!=null)setAmount(ImageFilterUtil.toFloatValue(o,"Amount")); 167 if((o=parameters.removeEL(KeyImpl.init("Turbulence")))!=null)setTurbulence(ImageFilterUtil.toFloatValue(o,"Turbulence")); 168 if((o=parameters.removeEL(KeyImpl.init("XScale")))!=null)setXScale(ImageFilterUtil.toFloatValue(o,"XScale")); 169 if((o=parameters.removeEL(KeyImpl.init("YScale")))!=null)setYScale(ImageFilterUtil.toFloatValue(o,"YScale")); 170 if((o=parameters.removeEL(KeyImpl.init("EdgeAction")))!=null)setEdgeAction(ImageFilterUtil.toString(o,"EdgeAction")); 171 if((o=parameters.removeEL(KeyImpl.init("Interpolation")))!=null)setInterpolation(ImageFilterUtil.toString(o,"Interpolation")); 172 173 // check for arguments not supported 174 if(parameters.size()>0) { 175 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, XScale, YScale, EdgeAction, Interpolation]"); 176 } 177 178 return filter(src, dst); 179 } 180}