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 import java.util.Random; 019 020 import railo.runtime.engine.ThreadLocalPageContext; 021 import railo.runtime.exp.FunctionException; 022 import railo.runtime.exp.PageException; 023 import railo.runtime.img.ImageUtil; 024 import railo.runtime.type.KeyImpl; 025 import railo.runtime.type.Struct; 026 import railo.runtime.type.util.CollectionUtil; 027 028 /** 029 * A filter which adds random noise into an image. 030 */ 031 public class NoiseFilter extends PointFilter implements DynFiltering { 032 033 /** 034 * Gaussian distribution for the noise. 035 */ 036 public final static int GAUSSIAN = 0; 037 038 /** 039 * Uniform distribution for the noise. 040 */ 041 public final static int UNIFORM = 1; 042 043 private int amount = 25; 044 private int distribution = UNIFORM; 045 private boolean monochrome = false; 046 private float density = 1; 047 private Random randomNumbers = new Random(); 048 049 public NoiseFilter() { 050 } 051 052 /** 053 * Set the amount of effect. 054 * @param amount the amount 055 * @min-value 0 056 * @max-value 1 057 * @see #getAmount 058 */ 059 public void setAmount(int amount) { 060 this.amount = amount; 061 } 062 063 /** 064 * Get the amount of noise. 065 * @return the amount 066 * @see #setAmount 067 */ 068 public int getAmount() { 069 return amount; 070 } 071 072 /** 073 * Set the distribution of the noise. 074 * @param distribution the distribution 075 * @see #getDistribution 076 */ 077 public void setDistribution( int distribution ) { 078 this.distribution = distribution; 079 } 080 081 /** 082 * Get the distribution of the noise. 083 * @return the distribution 084 * @see #setDistribution 085 */ 086 public int getDistribution() { 087 return distribution; 088 } 089 090 /** 091 * Set whether to use monochrome noise. 092 * @param monochrome true for monochrome noise 093 * @see #getMonochrome 094 */ 095 public void setMonochrome(boolean monochrome) { 096 this.monochrome = monochrome; 097 } 098 099 /** 100 * Get whether to use monochrome noise. 101 * @return true for monochrome noise 102 * @see #setMonochrome 103 */ 104 public boolean getMonochrome() { 105 return monochrome; 106 } 107 108 /** 109 * Set the density of the noise. 110 * @param density the density 111 * @see #getDensity 112 */ 113 public void setDensity( float density ) { 114 this.density = density; 115 } 116 117 /** 118 * Get the density of the noise. 119 * @return the density 120 * @see #setDensity 121 */ 122 public float getDensity() { 123 return density; 124 } 125 126 private int random(int x) { 127 x += (int)(((distribution == GAUSSIAN ? randomNumbers.nextGaussian() : 2*randomNumbers.nextFloat() - 1)) * amount); 128 if (x < 0) 129 x = 0; 130 else if (x > 0xff) 131 x = 0xff; 132 return x; 133 } 134 135 public int filterRGB(int x, int y, int rgb) { 136 if ( randomNumbers.nextFloat() <= density ) { 137 int a = rgb & 0xff000000; 138 int r = (rgb >> 16) & 0xff; 139 int g = (rgb >> 8) & 0xff; 140 int b = rgb & 0xff; 141 if (monochrome) { 142 int n = (int)(((distribution == GAUSSIAN ? randomNumbers.nextGaussian() : 2*randomNumbers.nextFloat() - 1)) * amount); 143 r = PixelUtils.clamp(r+n); 144 g = PixelUtils.clamp(g+n); 145 b = PixelUtils.clamp(b+n); 146 } else { 147 r = random(r); 148 g = random(g); 149 b = random(b); 150 } 151 return a | (r << 16) | (g << 8) | b; 152 } 153 return rgb; 154 } 155 156 public String toString() { 157 return "Stylize/Add Noise..."; 158 } 159 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src); 160 Object o; 161 if((o=parameters.removeEL(KeyImpl.init("Amount")))!=null)setAmount(ImageFilterUtil.toIntValue(o,"Amount")); 162 if((o=parameters.removeEL(KeyImpl.init("Monochrome")))!=null)setMonochrome(ImageFilterUtil.toBooleanValue(o,"Monochrome")); 163 if((o=parameters.removeEL(KeyImpl.init("Density")))!=null)setDensity(ImageFilterUtil.toFloatValue(o,"Density")); 164 if((o=parameters.removeEL(KeyImpl.init("Distribution")))!=null)setDistribution(ImageFilterUtil.toIntValue(o,"Distribution")); 165 if((o=parameters.removeEL(KeyImpl.init("Dimensions")))!=null){ 166 int[] dim=ImageFilterUtil.toDimensions(o,"Dimensions"); 167 setDimensions(dim[0],dim[1]); 168 } 169 170 // check for arguments not supported 171 if(parameters.size()>0) { 172 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, Monochrome, Density, Distribution, Dimensions]"); 173 } 174 175 return filter(src, dst); 176 } 177 }