001/*
002Copyright 2006 Jerry Huxtable
003
004Licensed under the Apache License, Version 2.0 (the "License");
005you may not use this file except in compliance with the License.
006You may obtain a copy of the License at
007
008   http://www.apache.org/licenses/LICENSE-2.0
009
010Unless required by applicable law or agreed to in writing, software
011distributed under the License is distributed on an "AS IS" BASIS,
012WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013See the License for the specific language governing permissions and
014limitations under the License.
015*/
016
017package com.jhlabs.image;
018
019import java.util.*;
020import java.awt.*;
021import java.awt.image.*;
022import com.jhlabs.math.*;
023
024public class QuiltFilter extends WholeImageFilter {
025
026        private Random randomGenerator;
027        private long seed = 567;
028        private int iterations = 25000;
029        private float a = -0.59f;
030        private float b = 0.2f;
031        private float c = 0.1f;
032        private float d = 0;
033        private int k = 0;
034        private Colormap colormap = new LinearColormap();
035
036        public QuiltFilter() {
037                randomGenerator = new Random();
038        }
039
040        public void randomize() {
041                seed = new Date().getTime();
042                randomGenerator.setSeed(seed);
043                a = randomGenerator.nextFloat();
044                b = randomGenerator.nextFloat();
045                c = randomGenerator.nextFloat();
046                d = randomGenerator.nextFloat();
047                k = randomGenerator.nextInt() % 20 - 10;
048        }
049        
050        /**
051         * Set the number of iterations the effect is performed.
052         * @param iterations the number of iterations
053     * @min-value 0
054     * @see #getIterations
055         */
056        public void setIterations(int iterations) {
057                this.iterations = iterations;
058        }
059
060        /**
061         * Get the number of iterations the effect is performed.
062         * @return the number of iterations
063     * @see #setIterations
064         */
065        public int getIterations() {
066                return iterations;
067        }
068
069        public void setA(float a) {
070                this.a = a;
071        }
072
073        public float getA() {
074                return a;
075        }
076
077        public void setB(float b) {
078                this.b = b;
079        }
080
081        public float getB() {
082                return b;
083        }
084
085        public void setC(float c) {
086                this.c = c;
087        }
088
089        public float getC() {
090                return c;
091        }
092
093        public void setD(float d) {
094                this.d = d;
095        }
096
097        public float getD() {
098                return d;
099        }
100
101        public void setK(int k) {
102                this.k = k;
103        }
104
105        public int getK() {
106                return k;
107        }
108
109    /**
110     * Set the colormap to be used for the filter.
111     * @param colormap the colormap
112     * @see #getColormap
113     */
114        public void setColormap(Colormap colormap) {
115                this.colormap = colormap;
116        }
117        
118    /**
119     * Get the colormap to be used for the filter.
120     * @return the colormap
121     * @see #setColormap
122     */
123        public Colormap getColormap() {
124                return colormap;
125        }
126        
127        protected int[] filterPixels( int width, int height, int[] inPixels, Rectangle transformedSpace ) {
128                int[] outPixels = new int[width * height];
129
130                int i = 0;
131                int max = 0;
132
133                float x = 0.1f;
134                float y = 0.3f;
135                
136                for (int n = 0; n < 20; n++) {
137                        float mx = ImageMath.PI*x;
138                        float my = ImageMath.PI*y;
139                        float smx2 = (float)Math.sin(2*mx);
140                        float smy2 = (float)Math.sin(2*my);
141                        float x1 = (float)(a*smx2 + b*smx2*Math.cos(2*my) +
142                                c*Math.sin(4*mx) + d*Math.sin(6*mx)*Math.cos(4*my) + k*x);
143                        x1 = x1 >= 0 ? x1 - (int)x1 : x1 - (int)x1 + 1;
144
145                        float y1 = (float)(a*smy2 + b*smy2*Math.cos(2*mx) +
146                                c*Math.sin(4*my) + d*Math.sin(6*my)*Math.cos(4*mx) + k*y);
147                        y1 = y1 >= 0 ? y1 - (int)y1 : y1 - (int)y1 + 1;
148                        x = x1;
149                        y = y1;
150                }
151
152                for (int n = 0; n < iterations; n++) {
153                        float mx = ImageMath.PI*x;
154                        float my = ImageMath.PI*y;
155                        float x1 = (float)(a*Math.sin(2*mx) + b*Math.sin(2*mx)*Math.cos(2*my) +
156                                c*Math.sin(4*mx) + d*Math.sin(6*mx)*Math.cos(4*my) + k*x);
157                        x1 = x1 >= 0 ? x1 - (int)x1 : x1 - (int)x1 + 1;
158
159                        float y1 = (float)(a*Math.sin(2*my) + b*Math.sin(2*my)*Math.cos(2*mx) +
160                                c*Math.sin(4*my) + d*Math.sin(6*my)*Math.cos(4*mx) + k*y);
161                        y1 = y1 >= 0 ? y1 - (int)y1 : y1 - (int)y1 + 1;
162                        x = x1;
163                        y = y1;
164                        int ix = (int)(width*x);
165                        int iy = (int)(height*y);
166                        if (ix >= 0 && ix < width && iy >= 0 && iy < height) {
167                                int t = outPixels[width*iy+ix]++;
168                                if (t > max)
169                                        max = t;
170                        }
171                }
172
173                if (colormap != null) {
174                        int index = 0;
175                        for (y = 0; y < height; y++) {
176                                for (x = 0; x < width; x++) {
177                                        outPixels[index] = colormap.getColor(outPixels[index] / (float)max);
178                                        index++;
179                                }
180                        }
181                }
182                return outPixels;
183        }
184
185        public String toString() {
186                return "Texture/Chaotic Quilt...";
187        }
188        
189}