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