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 allows the red, green and blue channels of an image to be mixed into each other.
047 */
048public class ChannelMixFilter extends PointFilter  implements DynFiltering {
049        
050        private int blueGreen, redBlue, greenRed;
051        private int intoR, intoG, intoB;
052        
053        public ChannelMixFilter() {
054                canFilterIndexColorModel = true;
055        }
056
057        public void setBlueGreen(int blueGreen) {
058                this.blueGreen = blueGreen;
059        }
060
061        public int getBlueGreen() {
062                return blueGreen;
063        }
064
065        public void setRedBlue(int redBlue) {
066                this.redBlue = redBlue;
067        }
068
069        public int getRedBlue() {
070                return redBlue;
071        }
072
073        public void setGreenRed(int greenRed) {
074                this.greenRed = greenRed;
075        }
076
077        public int getGreenRed() {
078                return greenRed;
079        }
080
081        public void setIntoR(int intoR) {
082                this.intoR = intoR;
083        }
084
085        public int getIntoR() {
086                return intoR;
087        }
088
089        public void setIntoG(int intoG) {
090                this.intoG = intoG;
091        }
092
093        public int getIntoG() {
094                return intoG;
095        }
096
097        public void setIntoB(int intoB) {
098                this.intoB = intoB;
099        }
100
101        public int getIntoB() {
102                return intoB;
103        }
104
105        public int filterRGB(int x, int y, int rgb) {
106                int a = rgb & 0xff000000;
107                int r = (rgb >> 16) & 0xff;
108                int g = (rgb >> 8) & 0xff;
109                int b = rgb & 0xff;
110                int nr = PixelUtils.clamp((intoR * (blueGreen*g+(255-blueGreen)*b)/255 + (255-intoR)*r)/255);
111                int ng = PixelUtils.clamp((intoG * (redBlue*b+(255-redBlue)*r)/255 + (255-intoG)*g)/255);
112                int nb = PixelUtils.clamp((intoB * (greenRed*r+(255-greenRed)*g)/255 + (255-intoB)*b)/255);
113                return a | (nr << 16) | (ng << 8) | nb;
114        }
115
116        public String toString() {
117                return "Colors/Mix Channels...";
118        }
119        public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src);
120                Object o;
121                if((o=parameters.removeEL(KeyImpl.init("BlueGreen")))!=null)setBlueGreen(ImageFilterUtil.toIntValue(o,"BlueGreen"));
122                if((o=parameters.removeEL(KeyImpl.init("RedBlue")))!=null)setRedBlue(ImageFilterUtil.toIntValue(o,"RedBlue"));
123                if((o=parameters.removeEL(KeyImpl.init("GreenRed")))!=null)setGreenRed(ImageFilterUtil.toIntValue(o,"GreenRed"));
124                if((o=parameters.removeEL(KeyImpl.init("IntoR")))!=null)setIntoR(ImageFilterUtil.toIntValue(o,"IntoR"));
125                if((o=parameters.removeEL(KeyImpl.init("IntoG")))!=null)setIntoG(ImageFilterUtil.toIntValue(o,"IntoG"));
126                if((o=parameters.removeEL(KeyImpl.init("IntoB")))!=null)setIntoB(ImageFilterUtil.toIntValue(o,"IntoB"));
127                if((o=parameters.removeEL(KeyImpl.init("Dimensions")))!=null){
128                        int[] dim=ImageFilterUtil.toDimensions(o,"Dimensions");
129                        setDimensions(dim[0],dim[1]);
130                }
131
132                // check for arguments not supported
133                if(parameters.size()>0) {
134                        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 [BlueGreen, RedBlue, GreenRed, IntoR, IntoG, IntoB, Dimensions]");
135                }
136
137                return filter(src, dst);
138        }
139}
140