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 for changing the gamma of an image.
049 */
050public class GammaFilter extends TransferFilter  implements DynFiltering {
051
052        private float rGamma, gGamma, bGamma;
053
054    /**
055     * Construct a GammaFilter.
056     */
057        public GammaFilter() {
058                this(1.0f);
059        }
060
061    /**
062     * Construct a GammaFilter.
063     * @param gamma the gamma level for all RGB channels
064     */
065        public GammaFilter(float gamma) {
066                this(gamma, gamma, gamma);
067        }
068
069    /**
070     * Construct a GammaFilter.
071     * @param rGamma the gamma level for the red channel
072     * @param gGamma the gamma level for the blue channel
073     * @param bGamma the gamma level for the green channel
074     */
075        public GammaFilter(float rGamma, float gGamma, float bGamma) {
076                setGamma(rGamma, gGamma, bGamma);
077        }
078
079    /**
080     * Set the gamma levels.
081     * @param rGamma the gamma level for the red channel
082     * @param gGamma the gamma level for the blue channel
083     * @param bGamma the gamma level for the green channel
084     * @see #getGamma
085     */
086        public void setGamma(float rGamma, float gGamma, float bGamma) {
087                this.rGamma = rGamma;
088                this.gGamma = gGamma;
089                this.bGamma = bGamma;
090                initialized = false;
091        }
092
093    /**
094     * Set the gamma level.
095     * @param gamma the gamma level for all RGB channels
096     * @see #getGamma
097     */
098        public void setGamma(float gamma) {
099                setGamma(gamma, gamma, gamma);
100        }
101        
102    /**
103     * Get the gamma level.
104     * @return the gamma level for all RGB channels
105     * @see #setGamma
106     */
107        public float getGamma() {
108                return rGamma;
109        }
110        
111    protected void initialize() {
112                rTable = makeTable(rGamma);
113
114                if (gGamma == rGamma)
115                        gTable = rTable;
116                else
117                        gTable = makeTable(gGamma);
118
119                if (bGamma == rGamma)
120                        bTable = rTable;
121                else if (bGamma == gGamma)
122                        bTable = gTable;
123                else
124                        bTable = makeTable(bGamma);
125        }
126
127        private int[] makeTable(float gamma) {
128                int[] table = new int[256];
129                for (int i = 0; i < 256; i++) {
130                        int v = (int) ((255.0 * Math.pow(i/255.0, 1.0 / gamma)) + 0.5);
131                        if (v > 255)
132                                v = 255;
133                        table[i] = v;
134                }
135                return table;
136        }
137
138        public String toString() {
139                return "Colors/Gamma...";
140        }
141
142        public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src);
143                Object o;
144                if((o=parameters.removeEL(KeyImpl.init("Gamma")))!=null)setGamma(ImageFilterUtil.toFloatValue(o,"Gamma"));
145                if((o=parameters.removeEL(KeyImpl.init("Dimensions")))!=null){
146                        int[] dim=ImageFilterUtil.toDimensions(o,"Dimensions");
147                        setDimensions(dim[0],dim[1]);
148                }
149
150                // check for arguments not supported
151                if(parameters.size()>0) {
152                        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 [Gamma, Gamma, Dimensions]");
153                }
154
155                return filter(src, dst);
156        }
157}
158