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.image.BufferedImage;
036
037import lucee.runtime.engine.ThreadLocalPageContext;
038import lucee.runtime.exp.FunctionException;
039import lucee.runtime.exp.PageException;
040import lucee.runtime.img.ImageUtil;
041import lucee.runtime.type.KeyImpl;
042import lucee.runtime.type.Struct;
043import lucee.runtime.type.util.CollectionUtil;
044
045/**
046 * A filter which adds Gaussian blur to an image, producing a glowing effect.
047 *
048 */
049public class GlowFilter extends GaussianFilter  implements DynFiltering {
050
051        private float amount = 0.5f;
052        
053        public GlowFilter() {
054                radius = 2;
055        }
056        
057        /**
058         * Set the amount of glow.
059         * @param amount the amount
060     * @min-value 0
061     * @max-value 1
062     * @see #getAmount
063         */
064        public void setAmount( float amount ) {
065                this.amount = amount;
066        }
067        
068        /**
069         * Get the amount of glow.
070         * @return the amount
071     * @see #setAmount
072         */
073        public float getAmount() {
074                return amount;
075        }
076        
077    public BufferedImage filter( BufferedImage src, BufferedImage dst ) {
078        int width = src.getWidth();
079        int height = src.getHeight();
080
081        if ( dst == null )
082            dst = createCompatibleDestImage( src, null );
083
084        int[] inPixels = new int[width*height];
085        int[] outPixels = new int[width*height];
086        src.getRGB( 0, 0, width, height, inPixels, 0, width );
087
088                if ( radius > 0 ) {
089                        convolveAndTranspose(kernel, inPixels, outPixels, width, height, alpha, alpha && premultiplyAlpha, false, CLAMP_EDGES);
090                        convolveAndTranspose(kernel, outPixels, inPixels, height, width, alpha, false, alpha && premultiplyAlpha, CLAMP_EDGES);
091                }
092
093        src.getRGB( 0, 0, width, height, outPixels, 0, width );
094
095                float a = 4*amount;
096
097                int index = 0;
098                for ( int y = 0; y < height; y++ ) {
099                        for ( int x = 0; x < width; x++ ) {
100                                int rgb1 = outPixels[index];
101                                int r1 = (rgb1 >> 16) & 0xff;
102                                int g1 = (rgb1 >> 8) & 0xff;
103                                int b1 = rgb1 & 0xff;
104
105                                int rgb2 = inPixels[index];
106                                int r2 = (rgb2 >> 16) & 0xff;
107                                int g2 = (rgb2 >> 8) & 0xff;
108                                int b2 = rgb2 & 0xff;
109
110                                r1 = PixelUtils.clamp( (int)(r1 + a * r2) );
111                                g1 = PixelUtils.clamp( (int)(g1 + a * g2) );
112                                b1 = PixelUtils.clamp( (int)(b1 + a * b2) );
113
114                                inPixels[index] = (rgb1 & 0xff000000) | (r1 << 16) | (g1 << 8) | b1;
115                                index++;
116                        }
117                }
118
119        dst.setRGB( 0, 0, width, height, inPixels, 0, width );
120        return dst;
121    }
122
123        public String toString() {
124                return "Blur/Glow...";
125        }
126        public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src);
127                Object o;
128                if((o=parameters.removeEL(KeyImpl.init("Amount")))!=null)setAmount(ImageFilterUtil.toFloatValue(o,"Amount"));
129                if((o=parameters.removeEL(KeyImpl.init("Radius")))!=null)setRadius(ImageFilterUtil.toFloatValue(o,"Radius"));
130                if((o=parameters.removeEL(KeyImpl.init("EdgeAction")))!=null)setEdgeAction(ImageFilterUtil.toString(o,"EdgeAction"));
131                if((o=parameters.removeEL(KeyImpl.init("UseAlpha")))!=null)setUseAlpha(ImageFilterUtil.toBooleanValue(o,"UseAlpha"));
132                if((o=parameters.removeEL(KeyImpl.init("PremultiplyAlpha")))!=null)setPremultiplyAlpha(ImageFilterUtil.toBooleanValue(o,"PremultiplyAlpha"));
133
134                // check for arguments not supported
135                if(parameters.size()>0) {
136                        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, Radius, Kernel, EdgeAction, UseAlpha, PremultiplyAlpha]");
137                }
138
139                return filter(src, dst);
140        }
141}