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
047/**
048 * A filter to change the saturation of an image. This works by calculating a grayscale version of the image
049 * and then extrapolating away from it.
050 */
051public class SaturationFilter extends PointFilter  implements DynFiltering {
052        
053        public float amount = 1;
054        
055    /**
056     * Construct a SaturationFilter.
057     */
058        public SaturationFilter() {
059        }
060
061    /**
062     * Construct a SaturationFilter.
063     * The amount of saturation change.
064     */
065        public SaturationFilter( float amount ) {
066                this.amount = amount;
067                canFilterIndexColorModel = true;
068        }
069
070    /**
071     * Set the amount of saturation change. 1 leaves the image unchanged, values between 0 and 1 desaturate, 0 completely
072     * desaturates it and values above 1 increase the saturation.
073     * @param amount the amount
074     */
075        public void setAmount( float amount ) {
076                this.amount = amount;
077        }
078        
079    /**
080     * Set the amount of saturation change.
081     * @return the amount
082     */
083        public float getAmount() {
084                return amount;
085        }
086        
087        public int filterRGB(int x, int y, int rgb) {
088                if ( amount != 1 ) {
089            int a = rgb & 0xff000000;
090            int r = (rgb >> 16) & 0xff;
091            int g = (rgb >> 8) & 0xff;
092            int b = rgb & 0xff;
093            int v = ( r + g + b )/3; // or a better brightness calculation if you prefer
094            r = PixelUtils.clamp( (int)(v + amount * (r-v)) );
095            g = PixelUtils.clamp( (int)(v + amount * (g-v)) );
096            b = PixelUtils.clamp( (int)(v + amount * (b-v)) );
097            return a | (r << 16) | (g << 8) | b;
098        }
099        return rgb;
100        }
101
102        public String toString() {
103                return "Colors/Saturation...";
104        }
105        public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src);
106                Object o;
107                if((o=parameters.removeEL(KeyImpl.init("Amount")))!=null)setAmount(ImageFilterUtil.toFloatValue(o,"Amount"));
108                if((o=parameters.removeEL(KeyImpl.init("Dimensions")))!=null){
109                        int[] dim=ImageFilterUtil.toDimensions(o,"Dimensions");
110                        setDimensions(dim[0],dim[1]);
111                }
112
113                // check for arguments not supported
114                if(parameters.size()>0) {
115                        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, Dimensions]");
116                }
117
118                return filter(src, dst);
119        }
120}
121