package com.hphoto.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; import com.jhlabs.math.*; /** * A filter which produces a water ripple distortion. */ public class WaterFilter extends TransformFilter { private float wavelength = 16; private float amplitude = 10; private float phase = 0; private float centreX = 0.5f; private float centreY = 0.5f; private float radius = 50; private float radius2 = 0; private float icentreX; private float icentreY; public WaterFilter() { setEdgeAction( CLAMP ); } /** * Set the wavelength of the ripples. * @param wavelength the wavelength * @see #getWavelength */ public void setWavelength(float wavelength) { this.wavelength = wavelength; } /** * Get the wavelength of the ripples. * @return the wavelength * @see #setWavelength */ public float getWavelength() { return wavelength; } /** * Set the amplitude of the ripples. * @param amplitude the amplitude * @see #getAmplitude */ public void setAmplitude(float amplitude) { this.amplitude = amplitude; } /** * Get the amplitude of the ripples. * @return the amplitude * @see #setAmplitude */ public float getAmplitude() { return amplitude; } /** * Set the phase of the ripples. * @param phase the phase * @see #getPhase */ public void setPhase(float phase) { this.phase = phase; } /** * Get the phase of the ripples. * @return the phase * @see #setPhase */ public float getPhase() { return phase; } /** * Set the centre of the effect in the X direction as a proportion of the image size. * @param centreX the center * @see #getCentreX */ public void setCentreX( float centreX ) { this.centreX = centreX; } /** * Get the centre of the effect in the X direction as a proportion of the image size. * @return the center * @see #setCentreX */ public float getCentreX() { return centreX; } /** * Set the centre of the effect in the Y direction as a proportion of the image size. * @param centreY the center * @see #getCentreY */ public void setCentreY( float centreY ) { this.centreY = centreY; } /** * Get the centre of the effect in the Y direction as a proportion of the image size. * @return the center * @see #setCentreY */ public float getCentreY() { return centreY; } /** * Set the centre of the effect as a proportion of the image size. * @param centre the center * @see #getCentre */ public void setCentre( Point2D centre ) { this.centreX = (float)centre.getX(); this.centreY = (float)centre.getY(); } /** * Get the centre of the effect as a proportion of the image size. * @return the center * @see #setCentre */ public Point2D getCentre() { return new Point2D.Float( centreX, centreY ); } /** * Set the radius of the effect. * @param radius the radius * @min-value 0 * @see #getRadius */ public void setRadius(float radius) { this.radius = radius; } /** * Get the radius of the effect. * @return the radius * @see #setRadius */ public float getRadius() { return radius; } private boolean inside(int v, int a, int b) { return a <= v && v <= b; } public BufferedImage filter( BufferedImage src, BufferedImage dst ) { icentreX = src.getWidth() * centreX; icentreY = src.getHeight() * centreY; if ( radius == 0 ) radius = Math.min(icentreX, icentreY); radius2 = radius*radius; return super.filter( src, dst ); } protected void transformInverse(int x, int y, float[] out) { float dx = x-icentreX; float dy = y-icentreY; float distance2 = dx*dx + dy*dy; if (distance2 > radius2) { out[0] = x; out[1] = y; } else { float distance = (float)Math.sqrt(distance2); float amount = amplitude * (float)Math.sin(distance / wavelength * ImageMath.TWO_PI - phase); amount *= (radius-distance)/radius; if ( distance != 0 ) amount *= wavelength/distance; out[0] = x + dx*amount; out[1] = y + dy*amount; } } public String toString() { return "Distort/Water Ripples..."; } }