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.image.BufferedImage; 018 019 import railo.runtime.engine.ThreadLocalPageContext; 020 import railo.runtime.exp.FunctionException; 021 import railo.runtime.exp.PageException; 022 import railo.runtime.img.ImageUtil; 023 import railo.runtime.img.math.Noise; 024 import railo.runtime.type.KeyImpl; 025 import railo.runtime.type.List; 026 import railo.runtime.type.Struct; 027 028 public class MarbleTexFilter extends PointFilter implements DynFiltering { 029 030 private float scale = 32; 031 private float stretch = 1.0f; 032 private float angle = 0.0f; 033 private float turbulence = 1; 034 private float turbulenceFactor = 0.5f; 035 private Colormap colormap; 036 private float m00 = 1.0f; 037 private float m01 = 0.0f; 038 private float m10 = 0.0f; 039 private float m11 = 1.0f; 040 041 public MarbleTexFilter() { 042 } 043 044 public void setScale(float scale) { 045 this.scale = scale; 046 } 047 048 public float getScale() { 049 return scale; 050 } 051 052 public void setStretch(float stretch) { 053 this.stretch = stretch; 054 } 055 056 public float getStretch() { 057 return stretch; 058 } 059 060 public void setAngle(float angle) { 061 this.angle = angle; 062 float cos = (float)Math.cos(angle); 063 float sin = (float)Math.sin(angle); 064 m00 = cos; 065 m01 = sin; 066 m10 = -sin; 067 m11 = cos; 068 } 069 070 public float getAngle() { 071 return angle; 072 } 073 074 public void setTurbulence(float turbulence) { 075 this.turbulence = turbulence; 076 } 077 078 public float getTurbulence() { 079 return turbulence; 080 } 081 082 public void setTurbulenceFactor(float turbulenceFactor) { 083 this.turbulenceFactor = turbulenceFactor; 084 } 085 086 public float getTurbulenceFactor() { 087 return turbulenceFactor; 088 } 089 090 public void setColormap(Colormap colormap) { 091 this.colormap = colormap; 092 } 093 094 public Colormap getColormap() { 095 return colormap; 096 } 097 098 public int filterRGB(int x, int y, int rgb) { 099 float nx = m00*x + m01*y; 100 float ny = m10*x + m11*y; 101 nx /= scale * stretch; 102 ny /= scale; 103 104 int a = rgb & 0xff000000; 105 if (colormap != null) { 106 // float f = Noise.turbulence2(nx, ny, turbulence); 107 // f = 3*turbulenceFactor*f+ny; 108 // f = Math.sin(f*Math.PI); 109 float chaos = turbulenceFactor*Noise.turbulence2(nx, ny, turbulence); 110 // float f = Math.sin(Math.sin(8.*chaos + 7*nx +3.*ny)); 111 float f = 3*turbulenceFactor*chaos+ny; 112 f = (float)Math.sin(f*Math.PI); 113 float perturb = (float)Math.sin(40.*chaos); 114 f += .2 * perturb; 115 return colormap.getColor(f); 116 } 117 float red, grn, blu; 118 float chaos, brownLayer, greenLayer; 119 float perturb, brownPerturb, greenPerturb, grnPerturb; 120 float t; 121 122 chaos = turbulenceFactor*Noise.turbulence2(nx, ny, turbulence); 123 t = (float)Math.sin(Math.sin(8.*chaos + 7*nx +3.*ny)); 124 125 greenLayer = brownLayer = Math.abs(t); 126 127 perturb = (float)Math.sin(40.*chaos); 128 perturb = Math.abs(perturb); 129 130 brownPerturb = .6f*perturb + 0.3f; 131 greenPerturb = .2f*perturb + 0.8f; 132 grnPerturb = .15f*perturb + 0.85f; 133 grn = 0.5f * (float)Math.pow(Math.abs(brownLayer), 0.3); 134 brownLayer = (float)Math.pow(0.5 * (brownLayer+1.0), 0.6) * brownPerturb; 135 greenLayer = (float)Math.pow(0.5 * (greenLayer+1.0), 0.6) * greenPerturb; 136 137 red = (0.5f*brownLayer + 0.35f*greenLayer)*2.0f*grn; 138 blu = (0.25f*brownLayer + 0.35f*greenLayer)*2.0f*grn; 139 grn *= Math.max(brownLayer, greenLayer) * grnPerturb; 140 int r = (rgb >> 16) & 0xff; 141 int g = (rgb >> 8) & 0xff; 142 int b = rgb & 0xff; 143 r = PixelUtils.clamp((int)(r*red)); 144 g = PixelUtils.clamp((int)(g*grn)); 145 b = PixelUtils.clamp((int)(b*blu)); 146 return (rgb & 0xff000000) | (r<<16) | (g<<8) | b; 147 } 148 149 public String toString() { 150 return "Texture/Marble Texture..."; 151 } 152 153 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src); 154 Object o; 155 if((o=parameters.removeEL(KeyImpl.init("Colormap")))!=null)setColormap(ImageFilterUtil.toColormap(o,"Colormap")); 156 if((o=parameters.removeEL(KeyImpl.init("Turbulence")))!=null)setTurbulence(ImageFilterUtil.toFloatValue(o,"Turbulence")); 157 if((o=parameters.removeEL(KeyImpl.init("Stretch")))!=null)setStretch(ImageFilterUtil.toFloatValue(o,"Stretch")); 158 if((o=parameters.removeEL(KeyImpl.init("Angle")))!=null)setAngle(ImageFilterUtil.toFloatValue(o,"Angle")); 159 if((o=parameters.removeEL(KeyImpl.init("TurbulenceFactor")))!=null)setTurbulenceFactor(ImageFilterUtil.toFloatValue(o,"TurbulenceFactor")); 160 if((o=parameters.removeEL(KeyImpl.init("Scale")))!=null)setScale(ImageFilterUtil.toFloatValue(o,"Scale")); 161 if((o=parameters.removeEL(KeyImpl.init("Dimensions")))!=null){ 162 int[] dim=ImageFilterUtil.toDimensions(o,"Dimensions"); 163 setDimensions(dim[0],dim[1]); 164 } 165 166 // check for arguments not supported 167 if(parameters.size()>0) { 168 throw new FunctionException(ThreadLocalPageContext.get(), "ImageFilter", 3, "parameters", "the parameter"+(parameters.size()>1?"s":"")+" ["+List.arrayToList(parameters.keysAsString(),", ")+"] "+(parameters.size()>1?"are":"is")+" not allowed, only the following parameters are supported [Colormap, Turbulence, Stretch, Angle, TurbulenceFactor, Scale, Dimensions]"); 169 } 170 171 return filter(src, dst); 172 } 173 }