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.Rectangle; 018 import java.awt.image.BufferedImage; 019 import java.util.Date; 020 import java.util.Random; 021 022 import railo.runtime.engine.ThreadLocalPageContext; 023 import railo.runtime.exp.FunctionException; 024 import railo.runtime.exp.PageException; 025 import railo.runtime.img.ImageUtil; 026 import railo.runtime.type.KeyImpl; 027 import railo.runtime.type.Struct; 028 import railo.runtime.type.util.CollectionUtil; 029 030 public class QuiltFilter extends WholeImageFilter implements DynFiltering { 031 032 private Random randomGenerator; 033 private long seed = 567; 034 private int iterations = 25000; 035 private float a = -0.59f; 036 private float b = 0.2f; 037 private float c = 0.1f; 038 private float d = 0; 039 private int k = 0; 040 private Colormap colormap = new LinearColormap(); 041 042 public QuiltFilter() { 043 randomGenerator = new Random(); 044 } 045 046 public void randomize() { 047 seed = new Date().getTime(); 048 randomGenerator.setSeed(seed); 049 a = randomGenerator.nextFloat(); 050 b = randomGenerator.nextFloat(); 051 c = randomGenerator.nextFloat(); 052 d = randomGenerator.nextFloat(); 053 k = randomGenerator.nextInt() % 20 - 10; 054 } 055 056 /** 057 * Set the number of iterations the effect is performed. 058 * @param iterations the number of iterations 059 * @min-value 0 060 * @see #getIterations 061 */ 062 public void setIterations(int iterations) { 063 this.iterations = iterations; 064 } 065 066 /** 067 * Get the number of iterations the effect is performed. 068 * @return the number of iterations 069 * @see #setIterations 070 */ 071 public int getIterations() { 072 return iterations; 073 } 074 075 public void setA(float a) { 076 this.a = a; 077 } 078 079 public float getA() { 080 return a; 081 } 082 083 public void setB(float b) { 084 this.b = b; 085 } 086 087 public float getB() { 088 return b; 089 } 090 091 public void setC(float c) { 092 this.c = c; 093 } 094 095 public float getC() { 096 return c; 097 } 098 099 public void setD(float d) { 100 this.d = d; 101 } 102 103 public float getD() { 104 return d; 105 } 106 107 public void setK(int k) { 108 this.k = k; 109 } 110 111 public int getK() { 112 return k; 113 } 114 115 /** 116 * Set the colormap to be used for the filter. 117 * @param colormap the colormap 118 * @see #getColormap 119 */ 120 public void setColormap(Colormap colormap) { 121 this.colormap = colormap; 122 } 123 124 /** 125 * Get the colormap to be used for the filter. 126 * @return the colormap 127 * @see #setColormap 128 */ 129 public Colormap getColormap() { 130 return colormap; 131 } 132 133 protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) { 134 int[] outPixels = new int[width * height]; 135 136 //int i = 0; 137 int max = 0; 138 139 float x = 0.1f; 140 float y = 0.3f; 141 142 for (int n = 0; n < 20; n++) { 143 float mx = ImageMath.PI*x; 144 float my = ImageMath.PI*y; 145 float smx2 = (float)Math.sin(2*mx); 146 float smy2 = (float)Math.sin(2*my); 147 float x1 = (float)(a*smx2 + b*smx2*Math.cos(2*my) + 148 c*Math.sin(4*mx) + d*Math.sin(6*mx)*Math.cos(4*my) + k*x); 149 x1 = x1 >= 0 ? x1 - (int)x1 : x1 - (int)x1 + 1; 150 151 float y1 = (float)(a*smy2 + b*smy2*Math.cos(2*mx) + 152 c*Math.sin(4*my) + d*Math.sin(6*my)*Math.cos(4*mx) + k*y); 153 y1 = y1 >= 0 ? y1 - (int)y1 : y1 - (int)y1 + 1; 154 x = x1; 155 y = y1; 156 } 157 158 for (int n = 0; n < iterations; n++) { 159 float mx = ImageMath.PI*x; 160 float my = ImageMath.PI*y; 161 float x1 = (float)(a*Math.sin(2*mx) + b*Math.sin(2*mx)*Math.cos(2*my) + 162 c*Math.sin(4*mx) + d*Math.sin(6*mx)*Math.cos(4*my) + k*x); 163 x1 = x1 >= 0 ? x1 - (int)x1 : x1 - (int)x1 + 1; 164 165 float y1 = (float)(a*Math.sin(2*my) + b*Math.sin(2*my)*Math.cos(2*mx) + 166 c*Math.sin(4*my) + d*Math.sin(6*my)*Math.cos(4*mx) + k*y); 167 y1 = y1 >= 0 ? y1 - (int)y1 : y1 - (int)y1 + 1; 168 x = x1; 169 y = y1; 170 int ix = (int)(width*x); 171 int iy = (int)(height*y); 172 if (ix >= 0 && ix < width && iy >= 0 && iy < height) { 173 int t = outPixels[width*iy+ix]++; 174 if (t > max) 175 max = t; 176 } 177 } 178 179 if (colormap != null) { 180 int index = 0; 181 for (y = 0; y < height; y++) { 182 for (x = 0; x < width; x++) { 183 outPixels[index] = colormap.getColor(outPixels[index] / (float)max); 184 index++; 185 } 186 } 187 } 188 return outPixels; 189 } 190 191 public String toString() { 192 return "Texture/Chaotic Quilt..."; 193 } 194 195 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src); 196 Object o; 197 if((o=parameters.removeEL(KeyImpl.init("Iterations")))!=null)setIterations(ImageFilterUtil.toIntValue(o,"Iterations")); 198 if((o=parameters.removeEL(KeyImpl.init("Colormap")))!=null)setColormap(ImageFilterUtil.toColormap(o,"Colormap")); 199 if((o=parameters.removeEL(KeyImpl.init("A")))!=null)setA(ImageFilterUtil.toFloatValue(o,"A")); 200 if((o=parameters.removeEL(KeyImpl.init("B")))!=null)setB(ImageFilterUtil.toFloatValue(o,"B")); 201 if((o=parameters.removeEL(KeyImpl.init("C")))!=null)setC(ImageFilterUtil.toFloatValue(o,"C")); 202 if((o=parameters.removeEL(KeyImpl.init("D")))!=null)setD(ImageFilterUtil.toFloatValue(o,"D")); 203 if((o=parameters.removeEL(KeyImpl.init("K")))!=null)setK(ImageFilterUtil.toIntValue(o,"K")); 204 205 // check for arguments not supported 206 if(parameters.size()>0) { 207 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 [Iterations, Colormap, A, B, C, D, K]"); 208 } 209 210 return filter(src, dst); 211 } 212 }