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;
036import java.util.Random;
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/**
047 * A filter which "dissolves" an image by thresholding the alpha channel with random numbers.
048 */
049public class DissolveFilter extends PointFilter  implements DynFiltering {
050        
051        private float density = 1;
052        private float softness = 0;
053        private float minDensity, maxDensity;
054        private Random randomNumbers;
055        
056        public DissolveFilter() {
057        }
058
059        /**
060         * Set the density of the image in the range 0..1.
061         * @param density the density
062     * @min-value 0
063     * @max-value 1
064     * @see #getDensity
065         */
066        public void setDensity( float density ) {
067                this.density = density;
068        }
069        
070        /**
071         * Get the density of the image.
072         * @return the density
073     * @see #setDensity
074         */
075        public float getDensity() {
076                return density;
077        }
078        
079        /**
080         * Set the softness of the dissolve in the range 0..1.
081         * @param softness the softness
082     * @min-value 0
083     * @max-value 1
084     * @see #getSoftness
085         */
086        public void setSoftness( float softness ) {
087                this.softness = softness;
088        }
089        
090        /**
091         * Get the softness of the dissolve.
092         * @return the softness
093     * @see #setSoftness
094         */
095        public float getSoftness() {
096                return softness;
097        }
098        
099    public BufferedImage filter( BufferedImage src, BufferedImage dst ) {
100                float d = (1-density) * (1+softness);
101                minDensity = d-softness;
102                maxDensity = d;
103                randomNumbers = new Random( 0 );
104                return super.filter( src, dst );
105        }
106        
107        public int filterRGB(int x, int y, int rgb) {
108                int a = (rgb >> 24) & 0xff;
109                float v = randomNumbers.nextFloat();
110                float f = ImageMath.smoothStep( minDensity, maxDensity, v );
111                return ((int)(a * f) << 24) | rgb & 0x00ffffff;
112        }
113
114        public String toString() {
115                return "Stylize/Dissolve...";
116        }
117        public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src);
118                Object o;
119                if((o=parameters.removeEL(KeyImpl.init("Density")))!=null)setDensity(ImageFilterUtil.toFloatValue(o,"Density"));
120                if((o=parameters.removeEL(KeyImpl.init("Softness")))!=null)setSoftness(ImageFilterUtil.toFloatValue(o,"Softness"));
121                if((o=parameters.removeEL(KeyImpl.init("Dimensions")))!=null){
122                        int[] dim=ImageFilterUtil.toDimensions(o,"Dimensions");
123                        setDimensions(dim[0],dim[1]);
124                }
125
126                // check for arguments not supported
127                if(parameters.size()>0) {
128                        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 [Density, Softness, Dimensions]");
129                }
130
131                return filter(src, dst);
132        }
133}