package com.hphoto.image; import java.awt.*; import java.awt.geom.*; import java.awt.image.*; /** * A Filter which distorts an image by twisting it from the centre out. * The twisting is centred at the centre of the image and extends out to the smallest of * the width and height. Pixels outside this radius are unaffected. */ public class TwirlFilter extends TransformFilter { private float angle = 0; private float centreX = 0.5f; private float centreY = 0.5f; private float radius = 100; private float radius2 = 0; private float icentreX; private float icentreY; /** * Construct a TwirlFilter with no distortion. */ public TwirlFilter() { setEdgeAction( CLAMP ); } /** * Set the angle of twirl in radians. 0 means no distortion. * @param angle the angle of twirl. This is the angle by which pixels at the nearest edge of the image will move. * @see #getAngle */ public void setAngle(float angle) { this.angle = angle; } /** * Get the angle of twist. * @return the angle in radians. * @see #setAngle */ public float getAngle() { return angle; } /** * 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; } 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 distance = dx*dx + dy*dy; if (distance > radius2) { out[0] = x; out[1] = y; } else { distance = (float)Math.sqrt(distance); float a = (float)Math.atan2(dy, dx) + angle * (radius-distance) / radius; out[0] = icentreX + distance*(float)Math.cos(a); out[1] = icentreY + distance*(float)Math.sin(a); } } public String toString() { return "Distort/Twirl..."; } }