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.AlphaComposite; 018 import java.awt.Color; 019 import java.awt.Graphics2D; 020 import java.awt.image.BufferedImage; 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.img.composite.AddComposite; 027 import railo.runtime.type.KeyImpl; 028 import railo.runtime.type.List; 029 import railo.runtime.type.Struct; 030 031 public class ShineFilter extends AbstractBufferedImageOp implements DynFiltering { 032 033 private float radius = 5; 034 private float angle = (float)Math.PI*7/4; 035 private float distance = 5; 036 private float bevel = 0.5f; 037 private boolean shadowOnly = false; 038 private int shineColor = 0xffffffff; 039 private float brightness = 0.2f; 040 private float softness = 0; 041 042 public ShineFilter() { 043 } 044 045 public void setAngle(float angle) { 046 this.angle = angle; 047 } 048 049 public float getAngle() { 050 return angle; 051 } 052 053 public void setDistance(float distance) { 054 this.distance = distance; 055 } 056 057 public float getDistance() { 058 return distance; 059 } 060 061 /** 062 * Set the radius of the kernel, and hence the amount of blur. The bigger the radius, the longer this filter will take. 063 * @param radius the radius of the blur in pixels. 064 */ 065 public void setRadius(float radius) { 066 this.radius = radius; 067 } 068 069 /** 070 * Get the radius of the kernel. 071 * @return the radius 072 */ 073 public float getRadius() { 074 return radius; 075 } 076 077 public void setBevel(float bevel) { 078 this.bevel = bevel; 079 } 080 081 public float getBevel() { 082 return bevel; 083 } 084 085 public void setShineColor(int shineColor) { 086 this.shineColor = shineColor; 087 } 088 089 public int getShineColor() { 090 return shineColor; 091 } 092 093 public void setShadowOnly(boolean shadowOnly) { 094 this.shadowOnly = shadowOnly; 095 } 096 097 public boolean getShadowOnly() { 098 return shadowOnly; 099 } 100 101 public void setBrightness(float brightness) { 102 this.brightness = brightness; 103 } 104 105 public float getBrightness() { 106 return brightness; 107 } 108 109 public void setSoftness(float softness) { 110 this.softness = softness; 111 } 112 113 public float getSoftness() { 114 return softness; 115 } 116 117 public BufferedImage filter( BufferedImage src, BufferedImage dst ) { 118 int width = src.getWidth(); 119 int height = src.getHeight(); 120 121 if ( dst == null ) 122 dst = createCompatibleDestImage( src, null ); 123 124 float xOffset = distance*(float)Math.cos(angle); 125 float yOffset = -distance*(float)Math.sin(angle); 126 127 BufferedImage matte = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 128 ErodeAlphaFilter s = new ErodeAlphaFilter( bevel * 10, 0.75f, 0.1f ); 129 matte = s.filter( src, (BufferedImage)null ); 130 131 BufferedImage shineLayer = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 132 Graphics2D g = shineLayer.createGraphics(); 133 g.setColor( new Color( shineColor ) ); 134 g.fillRect( 0, 0, width, height ); 135 g.setComposite( AlphaComposite.DstIn ); 136 g.drawRenderedImage( matte, null ); 137 g.setComposite( AlphaComposite.DstOut ); 138 g.translate( xOffset, yOffset ); 139 g.drawRenderedImage( matte, null ); 140 g.dispose(); 141 shineLayer = new GaussianFilter( radius ).filter( shineLayer, (BufferedImage)null ); 142 shineLayer = new RescaleFilter( 3*brightness ).filter( shineLayer, shineLayer ); 143 144 g = dst.createGraphics(); 145 g.drawRenderedImage( src, null ); 146 g.setComposite( new AddComposite( 1.0f ) ); 147 g.drawRenderedImage( shineLayer, null ); 148 g.dispose(); 149 150 return dst; 151 } 152 153 public String toString() { 154 return "Stylize/Shine..."; 155 } 156 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src); 157 Object o; 158 if((o=parameters.removeEL(KeyImpl.init("Radius")))!=null)setRadius(ImageFilterUtil.toFloatValue(o,"Radius")); 159 if((o=parameters.removeEL(KeyImpl.init("Brightness")))!=null)setBrightness(ImageFilterUtil.toFloatValue(o,"Brightness")); 160 if((o=parameters.removeEL(KeyImpl.init("Angle")))!=null)setAngle(ImageFilterUtil.toFloatValue(o,"Angle")); 161 if((o=parameters.removeEL(KeyImpl.init("Softness")))!=null)setSoftness(ImageFilterUtil.toFloatValue(o,"Softness")); 162 if((o=parameters.removeEL(KeyImpl.init("Distance")))!=null)setDistance(ImageFilterUtil.toFloatValue(o,"Distance")); 163 if((o=parameters.removeEL(KeyImpl.init("ShadowOnly")))!=null)setShadowOnly(ImageFilterUtil.toBooleanValue(o,"ShadowOnly")); 164 if((o=parameters.removeEL(KeyImpl.init("Bevel")))!=null)setBevel(ImageFilterUtil.toFloatValue(o,"Bevel")); 165 if((o=parameters.removeEL(KeyImpl.init("ShineColor")))!=null)setShineColor(ImageFilterUtil.toColorRGB(o,"ShineColor")); 166 167 // check for arguments not supported 168 if(parameters.size()>0) { 169 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 [Radius, Brightness, Angle, Softness, Distance, ShadowOnly, Bevel, ShineColor]"); 170 } 171 172 return filter(src, dst); 173 } 174 }