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.type.KeyImpl; 024 import railo.runtime.type.Struct; 025 import railo.runtime.type.util.CollectionUtil; 026 027 028 029 /** 030 * A filter which applies a crystallizing effect to an image, by producing Voronoi cells filled with colours from the image. 031 */ 032 public class CrystallizeFilter extends CellularFilter implements DynFiltering { 033 034 private float edgeThickness = 0.4f; 035 private boolean fadeEdges = false; 036 private int edgeColor = 0xff000000; 037 038 public CrystallizeFilter() { 039 setScale(16); 040 setRandomness(0.0f); 041 } 042 043 public void setEdgeThickness(float edgeThickness) { 044 this.edgeThickness = edgeThickness; 045 } 046 047 public float getEdgeThickness() { 048 return edgeThickness; 049 } 050 051 public void setFadeEdges(boolean fadeEdges) { 052 this.fadeEdges = fadeEdges; 053 } 054 055 public boolean getFadeEdges() { 056 return fadeEdges; 057 } 058 059 public void setEdgeColor(int edgeColor) { 060 this.edgeColor = edgeColor; 061 } 062 063 public int getEdgeColor() { 064 return edgeColor; 065 } 066 067 public int getPixel(int x, int y, int[] inPixels, int width, int height) { 068 float nx = m00*x + m01*y; 069 float ny = m10*x + m11*y; 070 nx /= scale; 071 ny /= scale * stretch; 072 nx += 1000; 073 ny += 1000; // Reduce artifacts around 0,0 074 float f = evaluate(nx, ny); 075 076 float f1 = results[0].distance; 077 float f2 = results[1].distance; 078 int srcx = ImageMath.clamp((int)((results[0].x-1000)*scale), 0, width-1); 079 int srcy = ImageMath.clamp((int)((results[0].y-1000)*scale), 0, height-1); 080 int v = inPixels[srcy * width + srcx]; 081 f = (f2 - f1) / edgeThickness; 082 f = ImageMath.smoothStep(0, edgeThickness, f); 083 if (fadeEdges) { 084 srcx = ImageMath.clamp((int)((results[1].x-1000)*scale), 0, width-1); 085 srcy = ImageMath.clamp((int)((results[1].y-1000)*scale), 0, height-1); 086 int v2 = inPixels[srcy * width + srcx]; 087 v2 = ImageMath.mixColors(0.5f, v2, v); 088 v = ImageMath.mixColors(f, v2, v); 089 } else 090 v = ImageMath.mixColors(f, edgeColor, v); 091 return v; 092 } 093 094 public String toString() { 095 return "Stylize/Crystallize..."; 096 } 097 098 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src); 099 Object o; 100 if((o=parameters.removeEL(KeyImpl.init("EdgeThickness")))!=null)setEdgeThickness(ImageFilterUtil.toFloatValue(o,"EdgeThickness")); 101 if((o=parameters.removeEL(KeyImpl.init("FadeEdges")))!=null)setFadeEdges(ImageFilterUtil.toBooleanValue(o,"FadeEdges")); 102 if((o=parameters.removeEL(KeyImpl.init("EdgeColor")))!=null)setEdgeColor(ImageFilterUtil.toColorRGB(o,"EdgeColor")); 103 if((o=parameters.removeEL(KeyImpl.init("Colormap")))!=null)setColormap(ImageFilterUtil.toColormap(o,"Colormap")); 104 if((o=parameters.removeEL(KeyImpl.init("Amount")))!=null)setAmount(ImageFilterUtil.toFloatValue(o,"Amount")); 105 if((o=parameters.removeEL(KeyImpl.init("Turbulence")))!=null)setTurbulence(ImageFilterUtil.toFloatValue(o,"Turbulence")); 106 if((o=parameters.removeEL(KeyImpl.init("Stretch")))!=null)setStretch(ImageFilterUtil.toFloatValue(o,"Stretch")); 107 if((o=parameters.removeEL(KeyImpl.init("Angle")))!=null)setAngle(ImageFilterUtil.toFloatValue(o,"Angle")); 108 if((o=parameters.removeEL(KeyImpl.init("AngleCoefficient")))!=null)setAngleCoefficient(ImageFilterUtil.toFloatValue(o,"AngleCoefficient")); 109 if((o=parameters.removeEL(KeyImpl.init("GradientCoefficient")))!=null)setGradientCoefficient(ImageFilterUtil.toFloatValue(o,"GradientCoefficient")); 110 if((o=parameters.removeEL(KeyImpl.init("F1")))!=null)setF1(ImageFilterUtil.toFloatValue(o,"F1")); 111 if((o=parameters.removeEL(KeyImpl.init("F2")))!=null)setF2(ImageFilterUtil.toFloatValue(o,"F2")); 112 if((o=parameters.removeEL(KeyImpl.init("F3")))!=null)setF3(ImageFilterUtil.toFloatValue(o,"F3")); 113 if((o=parameters.removeEL(KeyImpl.init("F4")))!=null)setF4(ImageFilterUtil.toFloatValue(o,"F4")); 114 if((o=parameters.removeEL(KeyImpl.init("Randomness")))!=null)setRandomness(ImageFilterUtil.toFloatValue(o,"Randomness")); 115 if((o=parameters.removeEL(KeyImpl.init("GridType")))!=null)setGridType(ImageFilterUtil.toString(o,"GridType")); 116 if((o=parameters.removeEL(KeyImpl.init("DistancePower")))!=null)setDistancePower(ImageFilterUtil.toFloatValue(o,"DistancePower")); 117 if((o=parameters.removeEL(KeyImpl.init("Scale")))!=null)setScale(ImageFilterUtil.toFloatValue(o,"Scale")); 118 119 // check for arguments not supported 120 if(parameters.size()>0) { 121 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 [EdgeThickness, FadeEdges, EdgeColor, Colormap, Amount, Turbulence, Stretch, Angle, Coefficient, AngleCoefficient, GradientCoefficient, F1, F2, F3, F4, Randomness, GridType, DistancePower, Scale]"); 122 } 123 124 return filter(src, dst); 125 } 126 }