001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019/* 020* 021 022Licensed under the Apache License, Version 2.0 (the "License"); 023you may not use this file except in compliance with the License. 024You may obtain a copy of the License at 025 026 http://www.apache.org/licenses/LICENSE-2.0 027 028Unless required by applicable law or agreed to in writing, software 029distributed under the License is distributed on an "AS IS" BASIS, 030WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 031See the License for the specific language governing permissions and 032limitations under the License. 033*/ 034 035package lucee.runtime.img.filter;import java.awt.AlphaComposite; 036import java.awt.Color; 037import java.awt.Graphics2D; 038import java.awt.image.BufferedImage; 039 040import lucee.runtime.engine.ThreadLocalPageContext; 041import lucee.runtime.exp.FunctionException; 042import lucee.runtime.exp.PageException; 043import lucee.runtime.img.ImageUtil; 044import lucee.runtime.img.composite.AddComposite; 045import lucee.runtime.type.KeyImpl; 046import lucee.runtime.type.Struct; 047import lucee.runtime.type.util.CollectionUtil; 048 049public class ShineFilter extends AbstractBufferedImageOp implements DynFiltering { 050 051 private float radius = 5; 052 private float angle = (float)Math.PI*7/4; 053 private float distance = 5; 054 private float bevel = 0.5f; 055 private boolean shadowOnly = false; 056 private int shineColor = 0xffffffff; 057 private float brightness = 0.2f; 058 private float softness = 0; 059 060 public ShineFilter() { 061 } 062 063 public void setAngle(float angle) { 064 this.angle = angle; 065 } 066 067 public float getAngle() { 068 return angle; 069 } 070 071 public void setDistance(float distance) { 072 this.distance = distance; 073 } 074 075 public float getDistance() { 076 return distance; 077 } 078 079 /** 080 * Set the radius of the kernel, and hence the amount of blur. The bigger the radius, the longer this filter will take. 081 * @param radius the radius of the blur in pixels. 082 */ 083 public void setRadius(float radius) { 084 this.radius = radius; 085 } 086 087 /** 088 * Get the radius of the kernel. 089 * @return the radius 090 */ 091 public float getRadius() { 092 return radius; 093 } 094 095 public void setBevel(float bevel) { 096 this.bevel = bevel; 097 } 098 099 public float getBevel() { 100 return bevel; 101 } 102 103 public void setShineColor(int shineColor) { 104 this.shineColor = shineColor; 105 } 106 107 public int getShineColor() { 108 return shineColor; 109 } 110 111 public void setShadowOnly(boolean shadowOnly) { 112 this.shadowOnly = shadowOnly; 113 } 114 115 public boolean getShadowOnly() { 116 return shadowOnly; 117 } 118 119 public void setBrightness(float brightness) { 120 this.brightness = brightness; 121 } 122 123 public float getBrightness() { 124 return brightness; 125 } 126 127 public void setSoftness(float softness) { 128 this.softness = softness; 129 } 130 131 public float getSoftness() { 132 return softness; 133 } 134 135 public BufferedImage filter( BufferedImage src, BufferedImage dst ) { 136 int width = src.getWidth(); 137 int height = src.getHeight(); 138 139 if ( dst == null ) 140 dst = createCompatibleDestImage( src, null ); 141 142 float xOffset = distance*(float)Math.cos(angle); 143 float yOffset = -distance*(float)Math.sin(angle); 144 145 BufferedImage matte = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 146 ErodeAlphaFilter s = new ErodeAlphaFilter( bevel * 10, 0.75f, 0.1f ); 147 matte = s.filter( src, (BufferedImage)null ); 148 149 BufferedImage shineLayer = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); 150 Graphics2D g = shineLayer.createGraphics(); 151 g.setColor( new Color( shineColor ) ); 152 g.fillRect( 0, 0, width, height ); 153 g.setComposite( AlphaComposite.DstIn ); 154 g.drawRenderedImage( matte, null ); 155 g.setComposite( AlphaComposite.DstOut ); 156 g.translate( xOffset, yOffset ); 157 g.drawRenderedImage( matte, null ); 158 g.dispose(); 159 shineLayer = new GaussianFilter( radius ).filter( shineLayer, (BufferedImage)null ); 160 shineLayer = new RescaleFilter( 3*brightness ).filter( shineLayer, shineLayer ); 161 162 g = dst.createGraphics(); 163 g.drawRenderedImage( src, null ); 164 g.setComposite( new AddComposite( 1.0f ) ); 165 g.drawRenderedImage( shineLayer, null ); 166 g.dispose(); 167 168 return dst; 169 } 170 171 public String toString() { 172 return "Stylize/Shine..."; 173 } 174 public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src); 175 Object o; 176 if((o=parameters.removeEL(KeyImpl.init("Radius")))!=null)setRadius(ImageFilterUtil.toFloatValue(o,"Radius")); 177 if((o=parameters.removeEL(KeyImpl.init("Brightness")))!=null)setBrightness(ImageFilterUtil.toFloatValue(o,"Brightness")); 178 if((o=parameters.removeEL(KeyImpl.init("Angle")))!=null)setAngle(ImageFilterUtil.toFloatValue(o,"Angle")); 179 if((o=parameters.removeEL(KeyImpl.init("Softness")))!=null)setSoftness(ImageFilterUtil.toFloatValue(o,"Softness")); 180 if((o=parameters.removeEL(KeyImpl.init("Distance")))!=null)setDistance(ImageFilterUtil.toFloatValue(o,"Distance")); 181 if((o=parameters.removeEL(KeyImpl.init("ShadowOnly")))!=null)setShadowOnly(ImageFilterUtil.toBooleanValue(o,"ShadowOnly")); 182 if((o=parameters.removeEL(KeyImpl.init("Bevel")))!=null)setBevel(ImageFilterUtil.toFloatValue(o,"Bevel")); 183 if((o=parameters.removeEL(KeyImpl.init("ShineColor")))!=null)setShineColor(ImageFilterUtil.toColorRGB(o,"ShineColor")); 184 185 // check for arguments not supported 186 if(parameters.size()>0) { 187 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 [Radius, Brightness, Angle, Softness, Distance, ShadowOnly, Bevel, ShineColor]"); 188 } 189 190 return filter(src, dst); 191 } 192}