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 by rippling it in the X or Y directions. 025 * The amplitude and wavelength of rippling can be specified as well as whether 026 * pixels going off the edges are wrapped or not. 027 */ 028public class RippleFilter extends TransformFilter { 029 030 /** 031 * Sine wave ripples. 032 */ 033 public final static int SINE = 0; 034 035 /** 036 * Sawtooth wave ripples. 037 */ 038 public final static int SAWTOOTH = 1; 039 040 /** 041 * Triangle wave ripples. 042 */ 043 public final static int TRIANGLE = 2; 044 045 /** 046 * Noise ripples. 047 */ 048 public final static int NOISE = 3; 049 050 private float xAmplitude, yAmplitude; 051 private float xWavelength, yWavelength; 052 private int waveType; 053 054 /** 055 * Construct a RippleFilter. 056 */ 057 public RippleFilter() { 058 xAmplitude = 5.0f; 059 yAmplitude = 0.0f; 060 xWavelength = yWavelength = 16.0f; 061 } 062 063 /** 064 * Set the amplitude of ripple in the X direction. 065 * @param xAmplitude the amplitude (in pixels). 066 * @see #getXAmplitude 067 */ 068 public void setXAmplitude(float xAmplitude) { 069 this.xAmplitude = xAmplitude; 070 } 071 072 /** 073 * Get the amplitude of ripple in the X direction. 074 * @return the amplitude (in pixels). 075 * @see #setXAmplitude 076 */ 077 public float getXAmplitude() { 078 return xAmplitude; 079 } 080 081 /** 082 * Set the wavelength of ripple in the X direction. 083 * @param xWavelength the wavelength (in pixels). 084 * @see #getXWavelength 085 */ 086 public void setXWavelength(float xWavelength) { 087 this.xWavelength = xWavelength; 088 } 089 090 /** 091 * Get the wavelength of ripple in the X direction. 092 * @return the wavelength (in pixels). 093 * @see #setXWavelength 094 */ 095 public float getXWavelength() { 096 return xWavelength; 097 } 098 099 /** 100 * Set the amplitude of ripple in the Y direction. 101 * @param yAmplitude the amplitude (in pixels). 102 * @see #getYAmplitude 103 */ 104 public void setYAmplitude(float yAmplitude) { 105 this.yAmplitude = yAmplitude; 106 } 107 108 /** 109 * Get the amplitude of ripple in the Y direction. 110 * @return the amplitude (in pixels). 111 * @see #setYAmplitude 112 */ 113 public float getYAmplitude() { 114 return yAmplitude; 115 } 116 117 /** 118 * Set the wavelength of ripple in the Y direction. 119 * @param yWavelength the wavelength (in pixels). 120 * @see #getYWavelength 121 */ 122 public void setYWavelength(float yWavelength) { 123 this.yWavelength = yWavelength; 124 } 125 126 /** 127 * Get the wavelength of ripple in the Y direction. 128 * @return the wavelength (in pixels). 129 * @see #setYWavelength 130 */ 131 public float getYWavelength() { 132 return yWavelength; 133 } 134 135 136 /** 137 * Set the wave type. 138 * @param waveType the type. 139 * @see #getWaveType 140 */ 141 public void setWaveType(int waveType) { 142 this.waveType = waveType; 143 } 144 145 /** 146 * Get the wave type. 147 * @return the type. 148 * @see #setWaveType 149 */ 150 public int getWaveType() { 151 return waveType; 152 } 153 154 protected void transformSpace(Rectangle r) { 155 if (edgeAction == ZERO) { 156 r.x -= (int)xAmplitude; 157 r.width += (int)(2*xAmplitude); 158 r.y -= (int)yAmplitude; 159 r.height += (int)(2*yAmplitude); 160 } 161 } 162 163 protected void transformInverse(int x, int y, float[] out) { 164 float nx = (float)y / xWavelength; 165 float ny = (float)x / yWavelength; 166 float fx, fy; 167 switch (waveType) { 168 case SINE: 169 default: 170 fx = (float)Math.sin(nx); 171 fy = (float)Math.sin(ny); 172 break; 173 case SAWTOOTH: 174 fx = ImageMath.mod(nx, 1); 175 fy = ImageMath.mod(ny, 1); 176 break; 177 case TRIANGLE: 178 fx = ImageMath.triangle(nx); 179 fy = ImageMath.triangle(ny); 180 break; 181 case NOISE: 182 fx = Noise.noise1(nx); 183 fy = Noise.noise1(ny); 184 break; 185 } 186 out[0] = x + xAmplitude * fx; 187 out[1] = y + yAmplitude * fy; 188 } 189 190 public String toString() { 191 return "Distort/Ripple..."; 192 } 193 194}