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.img.math.Noise;
042import lucee.runtime.type.KeyImpl;
043import lucee.runtime.type.Struct;
044import lucee.runtime.type.util.CollectionUtil;
045
046public class MarbleTexFilter extends PointFilter  implements DynFiltering {
047
048        private float scale = 32;
049        private float stretch = 1.0f;
050        private float angle = 0.0f;
051        private float turbulence = 1;
052        private float turbulenceFactor = 0.5f;
053        private Colormap colormap;
054        private float m00 = 1.0f;
055        private float m01 = 0.0f;
056        private float m10 = 0.0f;
057        private float m11 = 1.0f;
058
059        public MarbleTexFilter() {
060        }
061
062        public void setScale(float scale) {
063                this.scale = scale;
064        }
065
066        public float getScale() {
067                return scale;
068        }
069
070        public void setStretch(float stretch) {
071                this.stretch = stretch;
072        }
073
074        public float getStretch() {
075                return stretch;
076        }
077
078        public void setAngle(float angle) {
079                this.angle = angle;
080                float cos = (float)Math.cos(angle);
081                float sin = (float)Math.sin(angle);
082                m00 = cos;
083                m01 = sin;
084                m10 = -sin;
085                m11 = cos;
086        }
087
088        public float getAngle() {
089                return angle;
090        }
091
092        public void setTurbulence(float turbulence) {
093                this.turbulence = turbulence;
094        }
095
096        public float getTurbulence() {
097                return turbulence;
098        }
099
100        public void setTurbulenceFactor(float turbulenceFactor) {
101                this.turbulenceFactor = turbulenceFactor;
102        }
103
104        public float getTurbulenceFactor() {
105                return turbulenceFactor;
106        }
107
108        public void setColormap(Colormap colormap) {
109                this.colormap = colormap;
110        }
111        
112        public Colormap getColormap() {
113                return colormap;
114        }
115        
116        public int filterRGB(int x, int y, int rgb) {
117                float nx = m00*x + m01*y;
118                float ny = m10*x + m11*y;
119                nx /= scale * stretch;
120                ny /= scale;
121
122                //int a = rgb & 0xff000000;
123                if (colormap != null) {
124//                      float f = Noise.turbulence2(nx, ny, turbulence);
125//                      f = 3*turbulenceFactor*f+ny;
126//                      f = Math.sin(f*Math.PI);
127                        float chaos = turbulenceFactor*Noise.turbulence2(nx, ny, turbulence);
128//                      float f = Math.sin(Math.sin(8.*chaos + 7*nx +3.*ny));
129                        float f = 3*turbulenceFactor*chaos+ny;
130                        f = (float)Math.sin(f*Math.PI);
131                        float perturb = (float)Math.sin(40.*chaos);
132                        f += .2 * perturb;
133                        return colormap.getColor(f);
134                } 
135                float red, grn, blu;
136                float chaos, brownLayer, greenLayer;
137                float perturb, brownPerturb, greenPerturb, grnPerturb;
138                float t;
139
140                chaos = turbulenceFactor*Noise.turbulence2(nx, ny, turbulence);
141                t = (float)Math.sin(Math.sin(8.*chaos + 7*nx +3.*ny));
142
143                greenLayer = brownLayer = Math.abs(t);
144
145                perturb = (float)Math.sin(40.*chaos);
146                perturb = Math.abs(perturb);
147
148                brownPerturb = .6f*perturb + 0.3f;
149                greenPerturb = .2f*perturb + 0.8f;
150                grnPerturb = .15f*perturb + 0.85f;
151                grn = 0.5f * (float)Math.pow(Math.abs(brownLayer), 0.3);
152                brownLayer = (float)Math.pow(0.5 * (brownLayer+1.0), 0.6) * brownPerturb;
153                greenLayer = (float)Math.pow(0.5 * (greenLayer+1.0), 0.6) * greenPerturb;
154
155                red = (0.5f*brownLayer + 0.35f*greenLayer)*2.0f*grn;
156                blu = (0.25f*brownLayer + 0.35f*greenLayer)*2.0f*grn;
157                grn *= Math.max(brownLayer, greenLayer) * grnPerturb;
158                int r = (rgb >> 16) & 0xff;
159                int g = (rgb >> 8) & 0xff;
160                int b = rgb & 0xff;
161                r = PixelUtils.clamp((int)(r*red));
162                g = PixelUtils.clamp((int)(g*grn));
163                b = PixelUtils.clamp((int)(b*blu));
164                return (rgb & 0xff000000) | (r<<16) | (g<<8) | b;
165        }
166
167        public String toString() {
168                return "Texture/Marble Texture...";
169        }
170        
171        public BufferedImage filter(BufferedImage src, Struct parameters) throws PageException {BufferedImage dst=ImageUtil.createBufferedImage(src);
172                Object o;
173                if((o=parameters.removeEL(KeyImpl.init("Colormap")))!=null)setColormap(ImageFilterUtil.toColormap(o,"Colormap"));
174                if((o=parameters.removeEL(KeyImpl.init("Turbulence")))!=null)setTurbulence(ImageFilterUtil.toFloatValue(o,"Turbulence"));
175                if((o=parameters.removeEL(KeyImpl.init("Stretch")))!=null)setStretch(ImageFilterUtil.toFloatValue(o,"Stretch"));
176                if((o=parameters.removeEL(KeyImpl.init("Angle")))!=null)setAngle(ImageFilterUtil.toFloatValue(o,"Angle"));
177                if((o=parameters.removeEL(KeyImpl.init("TurbulenceFactor")))!=null)setTurbulenceFactor(ImageFilterUtil.toFloatValue(o,"TurbulenceFactor"));
178                if((o=parameters.removeEL(KeyImpl.init("Scale")))!=null)setScale(ImageFilterUtil.toFloatValue(o,"Scale"));
179                if((o=parameters.removeEL(KeyImpl.init("Dimensions")))!=null){
180                        int[] dim=ImageFilterUtil.toDimensions(o,"Dimensions");
181                        setDimensions(dim[0],dim[1]);
182                }
183
184                // check for arguments not supported
185                if(parameters.size()>0) {
186                        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 [Colormap, Turbulence, Stretch, Angle, TurbulenceFactor, Scale, Dimensions]");
187                }
188
189                return filter(src, dst);
190        }
191}