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.Color;
036import java.awt.image.BufferedImage;
037
038import lucee.runtime.engine.ThreadLocalPageContext;
039import lucee.runtime.exp.FunctionException;
040import lucee.runtime.exp.PageException;
041import lucee.runtime.img.ImageUtil;
042import lucee.runtime.type.KeyImpl;
043import lucee.runtime.type.Struct;
044import lucee.runtime.type.util.CollectionUtil;
045/**
046 * A filter which can be used to produce wipes by transferring the luma of a Destination image into the alpha channel of the source.
047 */
048public class ChromaKeyFilter extends AbstractBufferedImageOp  implements DynFiltering {
049        
050        private float hTolerance = 0;
051        private float sTolerance = 0;
052        private float bTolerance = 0;
053        private int color;
054
055        public ChromaKeyFilter() {
056        }
057
058        /**
059         * Set the tolerance of the image in the range 0..1.
060         * *arg tolerance The tolerance
061         */
062        public void setHTolerance( float hTolerance ) {
063                this.hTolerance = hTolerance;
064        }
065        
066        public float getHTolerance() {
067                return hTolerance;
068        }
069        
070        public void setSTolerance( float sTolerance ) {
071                this.sTolerance = sTolerance;
072        }
073        
074        public float getSTolerance() {
075                return sTolerance;
076        }
077        
078        public void setBTolerance( float bTolerance ) {
079                this.bTolerance = bTolerance;
080        }
081        
082        public float getBTolerance() {
083                return bTolerance;
084        }
085        
086        public void setColor( int color ) {
087                this.color = color;
088        }
089        
090        public int getColor() {
091                return color;
092        }
093                
094    public BufferedImage filter( BufferedImage src, BufferedImage dst ) {
095        int width = src.getWidth();
096        int height = src.getHeight();
097                //int type = src.getType();
098                //WritableRaster srcRaster = 
099        src.getRaster();
100
101        if ( dst == null )
102            dst = createCompatibleDestImage( src, null );
103                //WritableRaster dstRaster = 
104        dst.getRaster();
105
106                float[] hsb1 = null;
107                float[] hsb2 = null;
108                int rgb2 = color;
109                int r2 = (rgb2 >> 16) & 0xff;
110                int g2 = (rgb2 >> 8) & 0xff;
111                int b2 = rgb2 & 0xff;
112                hsb2 = Color.RGBtoHSB( r2, b2, g2, hsb2 );
113                int[] inPixels = null;
114                for ( int y = 0; y < height; y++ ) {
115                        inPixels = getRGB( src, 0, y, width, 1, inPixels );
116                        for ( int x = 0; x < width; x++ ) {
117                                int rgb1 = inPixels[x];
118
119                                int r1 = (rgb1 >> 16) & 0xff;
120                                int g1 = (rgb1 >> 8) & 0xff;
121                                int b1 = rgb1 & 0xff;
122                                hsb1 = Color.RGBtoHSB( r1, b1, g1, hsb1 );
123//                    int tolerance = (int)(255*tolerance);
124//                    return Math.abs(r1-r2) <= tolerance && Math.abs(g1-g2) <= tolerance && Math.abs(b1-b2) <= tolerance;
125
126//                   if ( PixelUtils.nearColors( in, clean, (int)(255*tolerance) ) )
127                                if ( Math.abs( hsb1[0] - hsb2[0] ) < hTolerance && Math.abs( hsb1[1] - hsb2[1] ) < sTolerance && Math.abs( hsb1[2] - hsb2[2] ) < bTolerance )
128                                        inPixels[x] = rgb1 & 0xffffff;
129                                else
130                                        inPixels[x] = rgb1;
131                        }
132                        setRGB( dst, 0, y, width, 1, inPixels );
133                }
134
135        return dst;
136    }
137
138        public String toString() {
139                return "Keying/Chroma Key...";
140        }
141        public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src);
142                Object o;
143                if((o=parameters.removeEL(KeyImpl.init("HTolerance")))!=null)setHTolerance(ImageFilterUtil.toFloatValue(o,"HTolerance"));
144                if((o=parameters.removeEL(KeyImpl.init("STolerance")))!=null)setSTolerance(ImageFilterUtil.toFloatValue(o,"STolerance"));
145                if((o=parameters.removeEL(KeyImpl.init("BTolerance")))!=null)setBTolerance(ImageFilterUtil.toFloatValue(o,"BTolerance"));
146                if((o=parameters.removeEL(KeyImpl.init("Color")))!=null)setColor(ImageFilterUtil.toIntValue(o,"Color"));
147
148                // check for arguments not supported
149                if(parameters.size()>0) {
150                        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 [HTolerance, STolerance, BTolerance, Color]");
151                }
152
153                return filter(src, dst);
154        }
155}