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.awt.image.*;
020import com.jhlabs.math.*;
021
022/**
023 * A filter which produces a simulated wood texture. This is a bit of a hack, but might be usefult to some people.
024 */
025public class WoodFilter extends PointFilter {
026
027        private float scale = 200;
028        private float stretch = 10.0f;
029        private float angle = (float)Math.PI/2;
030        private float rings = 0.5f;
031        private float turbulence = 0.0f;
032        private float fibres = 0.5f;
033        private float gain = 0.8f;
034        private float m00 = 1.0f;
035        private float m01 = 0.0f;
036        private float m10 = 0.0f;
037        private float m11 = 1.0f;
038        private Colormap colormap = new LinearColormap( 0xffe5c494, 0xff987b51 );
039
040        /**
041     * Construct a WoodFilter.
042     */
043    public WoodFilter() {
044        }
045
046        /**
047     * Specifies the rings value.
048     * @param rings the rings value.
049     * @min-value 0
050     * @max-value 1
051     * @see #getRings
052     */
053    public void setRings(float rings) {
054                this.rings = rings;
055        }
056
057    /**
058     * Returns the rings value.
059     * @return the rings value.
060     * @see #setRings
061     */
062        public float getRings() {
063                return rings;
064        }
065
066        /**
067     * Specifies the scale of the texture.
068     * @param scale the scale of the texture.
069     * @min-value 1
070     * @max-value 300+
071     * @see #getScale
072     */
073        public void setScale(float scale) {
074                this.scale = scale;
075        }
076
077        /**
078     * Returns the scale of the texture.
079     * @return the scale of the texture.
080     * @see #setScale
081     */
082        public float getScale() {
083                return scale;
084        }
085
086        /**
087     * Specifies the stretch factor of the texture.
088     * @param stretch the stretch factor of the texture.
089     * @min-value 1
090     * @max-value 50+
091     * @see #getStretch
092     */
093        public void setStretch(float stretch) {
094                this.stretch = stretch;
095        }
096
097        /**
098     * Returns the stretch factor of the texture.
099     * @return the stretch factor of the texture.
100     * @see #setStretch
101     */
102        public float getStretch() {
103                return stretch;
104        }
105
106        /**
107     * Specifies the angle of the texture.
108     * @param angle the angle of the texture.
109     * @angle
110     * @see #getAngle
111     */
112        public void setAngle(float angle) {
113                this.angle = angle;
114                float cos = (float)Math.cos(angle);
115                float sin = (float)Math.sin(angle);
116                m00 = cos;
117                m01 = sin;
118                m10 = -sin;
119                m11 = cos;
120        }
121
122        /**
123     * Returns the angle of the texture.
124     * @return the angle of the texture.
125     * @see #setAngle
126     */
127        public float getAngle() {
128                return angle;
129        }
130
131        /**
132     * Specifies the turbulence of the texture.
133     * @param turbulence the turbulence of the texture.
134     * @min-value 0
135     * @max-value 1
136     * @see #getTurbulence
137     */
138        public void setTurbulence(float turbulence) {
139                this.turbulence = turbulence;
140        }
141
142        /**
143     * Returns the turbulence of the texture.
144     * @return the turbulence of the texture.
145     * @see #setTurbulence
146     */
147        public float getTurbulence() {
148                return turbulence;
149        }
150
151        /**
152     * Specifies the amount of fibres in the texture.
153     * @param fibres the amount of fibres in the texture.
154     * @min-value 0
155     * @max-value 1
156     * @see #getFibres
157     */
158        public void setFibres(float fibres) {
159                this.fibres = fibres;
160        }
161
162        /**
163     * Returns the amount of fibres in  the texture.
164     * @return the amount of fibres in the texture.
165     * @see #setFibres
166     */
167        public float getFibres() {
168                return fibres;
169        }
170
171        /**
172     * Specifies the gain of the texture.
173     * @param gain the gain of the texture.
174     * @min-value 0
175     * @max-value 1
176     * @see #getGain
177     */
178        public void setGain(float gain) {
179                this.gain = gain;
180        }
181
182        /**
183     * Returns the gain of the texture.
184     * @return the gain of the texture.
185     * @see #setGain
186     */
187        public float getGain() {
188                return gain;
189        }
190
191    /**
192     * Set the colormap to be used for the filter.
193     * @param colormap the colormap
194     * @see #getColormap
195     */
196        public void setColormap(Colormap colormap) {
197                this.colormap = colormap;
198        }
199        
200    /**
201     * Get the colormap to be used for the filter.
202     * @return the colormap
203     * @see #setColormap
204     */
205        public Colormap getColormap() {
206                return colormap;
207        }
208        
209        public int filterRGB(int x, int y, int rgb) {
210                float nx = m00*x + m01*y;
211                float ny = m10*x + m11*y;
212                nx /= scale;
213                ny /= scale * stretch;
214                float f = Noise.noise2(nx, ny);
215        f += 0.1f*turbulence * Noise.noise2(nx*0.05f, ny*20);
216                f = (f * 0.5f) + 0.5f;
217
218        f *= rings*50;
219        f = f-(int)f;
220        f *= 1-ImageMath.smoothStep(gain, 1.0f, f);
221
222        f += fibres*Noise.noise2(nx*scale, ny*50);
223
224                int a = rgb & 0xff000000;
225                int v;
226                if (colormap != null)
227                        v = colormap.getColor(f);
228                else {
229                        v = PixelUtils.clamp((int)(f*255));
230                        int r = v << 16;
231                        int g = v << 8;
232                        int b = v;
233                        v = a|r|g|b;
234                }
235
236                return v;
237        }
238
239        public String toString() {
240                return "Texture/Wood...";
241        }
242        
243}