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.*;
020import java.awt.image.*;
021import com.jhlabs.math.*;
022
023/**
024 * A filter which distorts an image as if it were underwater.
025 */
026public class SwimFilter extends TransformFilter {
027
028        private float scale = 32;
029        private float stretch = 1.0f;
030        private float angle = 0.0f;
031        private float amount = 1.0f;
032        private float turbulence = 1.0f;
033        private float time = 0.0f;
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
039        public SwimFilter() {
040        }
041        
042        /**
043         * Set the amount of swim.
044         * @param amount the amount of swim
045     * @min-value 0
046     * @max-value 100+
047     * @see #getAmount
048         */
049        public void setAmount(float amount) {
050                this.amount = amount;
051        }
052        
053        /**
054         * Get the amount of swim.
055         * @return the amount swim
056     * @see #setAmount
057         */
058        public float getAmount() {
059                return amount;
060        }
061        
062        /**
063     * Specifies the scale of the distortion.
064     * @param scale the scale of the distortion.
065     * @min-value 1
066     * @max-value 300+
067     * @see #getScale
068     */
069        public void setScale(float scale) {
070                this.scale = scale;
071        }
072
073        /**
074     * Returns the scale of the distortion.
075     * @return the scale of the distortion.
076     * @see #setScale
077     */
078        public float getScale() {
079                return scale;
080        }
081
082        /**
083     * Specifies the stretch factor of the distortion.
084     * @param stretch the stretch factor of the distortion.
085     * @min-value 1
086     * @max-value 50+
087     * @see #getStretch
088     */
089        public void setStretch(float stretch) {
090                this.stretch = stretch;
091        }
092
093        /**
094     * Returns the stretch factor of the distortion.
095     * @return the stretch factor of the distortion.
096     * @see #setStretch
097     */
098        public float getStretch() {
099                return stretch;
100        }
101
102        /**
103     * Specifies the angle of the effect.
104     * @param angle the angle of the effect.
105     * @angle
106     * @see #getAngle
107     */
108        public void setAngle(float angle) {
109                this.angle = angle;
110                float cos = (float)Math.cos(angle);
111                float sin = (float)Math.sin(angle);
112                m00 = cos;
113                m01 = sin;
114                m10 = -sin;
115                m11 = cos;
116        }
117
118        /**
119     * Returns the angle of the effect.
120     * @return the angle of the effect.
121     * @see #setAngle
122     */
123        public float getAngle() {
124                return angle;
125        }
126
127        /**
128     * Specifies the turbulence of the texture.
129     * @param turbulence the turbulence of the texture.
130     * @min-value 0
131     * @max-value 1
132     * @see #getTurbulence
133     */
134        public void setTurbulence(float turbulence) {
135                this.turbulence = turbulence;
136        }
137
138        /**
139     * Returns the turbulence of the effect.
140     * @return the turbulence of the effect.
141     * @see #setTurbulence
142     */
143        public float getTurbulence() {
144                return turbulence;
145        }
146
147        /**
148     * Specifies the time. Use this to animate the effect.
149     * @param time the time.
150     * @angle
151     * @see #getTime
152     */
153        public void setTime(float time) {
154                this.time = time;
155        }
156
157        /**
158     * Returns the time.
159     * @return the time.
160     * @see #setTime
161     */
162        public float getTime() {
163                return time;
164        }
165
166        protected void transformInverse(int x, int y, float[] out) {
167                float nx = m00*x + m01*y;
168                float ny = m10*x + m11*y;
169                nx /= scale;
170                ny /= scale * stretch;
171
172                if ( turbulence == 1.0f ) {
173                        out[0] = x + amount * Noise.noise3(nx+0.5f, ny, time);
174                        out[1] = y + amount * Noise.noise3(nx, ny+0.5f, time);
175                } else {
176                        out[0] = x + amount * Noise.turbulence3(nx+0.5f, ny, turbulence, time);
177                        out[1] = y + amount * Noise.turbulence3(nx, ny+0.5f, turbulence, time);
178                }
179        }
180
181        public String toString() {
182                return "Distort/Swim...";
183        }
184}