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 * A filter which can be used to produce wipes by transferring the luma of a mask image into the alpha channel of the source. 029 */ 030 public class GradientWipeFilter extends AbstractBufferedImageOp implements DynFiltering { 031 032 private float density = 0; 033 private float softness = 0; 034 private boolean invert; 035 private BufferedImage mask; 036 037 public GradientWipeFilter() { 038 } 039 040 /** 041 * Set the density of the image in the range 0..1. 042 * *arg density The density 043 */ 044 public void setDensity( float density ) { 045 this.density = density; 046 } 047 048 public float getDensity() { 049 return density; 050 } 051 052 /** 053 * Set the softness of the dissolve in the range 0..1. 054 * @param softness the softness 055 * @min-value 0 056 * @max-value 1 057 * @see #getSoftness 058 */ 059 public void setSoftness( float softness ) { 060 this.softness = softness; 061 } 062 063 /** 064 * Get the softness of the dissolve. 065 * @return the softness 066 * @see #setSoftness 067 */ 068 public float getSoftness() { 069 return softness; 070 } 071 072 public void setMask( BufferedImage mask ) { 073 this.mask = mask; 074 } 075 076 public BufferedImage getMask() { 077 return mask; 078 } 079 080 public void setInvert( boolean invert ) { 081 this.invert = invert; 082 } 083 084 public boolean getInvert() { 085 return invert; 086 } 087 088 public BufferedImage filter( BufferedImage src, BufferedImage dst ) { 089 int width = src.getWidth(); 090 int height = src.getHeight(); 091 092 if ( dst == null ) 093 dst = createCompatibleDestImage( src, null ); 094 if ( mask == null ) 095 return dst; 096 097 int maskWidth = mask.getWidth(); 098 int maskHeight = mask.getHeight(); 099 100 float d = density * (1+softness); 101 float lower = 255 * (d-softness); 102 float upper = 255 * d; 103 104 int[] inPixels = new int[width]; 105 int[] maskPixels = new int[maskWidth]; 106 107 for ( int y = 0; y < height; y++ ) { 108 getRGB( src, 0, y, width, 1, inPixels ); 109 getRGB( mask, 0, y % maskHeight, maskWidth, 1, maskPixels ); 110 111 for ( int x = 0; x < width; x++ ) { 112 int maskRGB = maskPixels[x % maskWidth]; 113 int inRGB = inPixels[x]; 114 int v = PixelUtils.brightness( maskRGB ); 115 float f = ImageMath.smoothStep( lower, upper, v ); 116 int a = (int)(255 * f); 117 118 if ( invert ) 119 a = 255-a; 120 inPixels[x] = (a << 24) | (inRGB & 0x00ffffff); 121 } 122 123 setRGB( dst, 0, y, width, 1, inPixels ); 124 } 125 126 return dst; 127 } 128 129 public String toString() { 130 return "Transitions/Gradient Wipe..."; 131 } 132 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src); 133 Object o; 134 if((o=parameters.removeEL(KeyImpl.init("Density")))!=null)setDensity(ImageFilterUtil.toFloatValue(o,"Density")); 135 if((o=parameters.removeEL(KeyImpl.init("Softness")))!=null)setSoftness(ImageFilterUtil.toFloatValue(o,"Softness")); 136 if((o=parameters.removeEL(KeyImpl.init("Invert")))!=null)setInvert(ImageFilterUtil.toBooleanValue(o,"Invert")); 137 if((o=parameters.removeEL(KeyImpl.init("Mask")))!=null)setMask(ImageFilterUtil.toBufferedImage(o,"Mask")); 138 139 // check for arguments not supported 140 if(parameters.size()>0) { 141 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 [Density, Softness, Invert, Mask]"); 142 } 143 144 return filter(src, dst); 145 } 146 }