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.geom.*;
021import java.awt.image.*;
022
023/**
024 * A filter which wraps an image around a circular arc.
025 */
026public class CircleFilter extends TransformFilter {
027
028        private float radius = 10;
029        private float height = 20;
030        private float angle = 0;
031        private float spreadAngle = (float)Math.PI;
032        private float centreX = 0.5f;
033        private float centreY = 0.5f;
034
035        private float icentreX;
036        private float icentreY;
037        private float iWidth;
038        private float iHeight;
039
040        /**
041     * Construct a CircleFilter.
042     */
043    public CircleFilter() {
044                setEdgeAction( ZERO );
045        }
046
047        /**
048     * Set the height of the arc.
049     * @param height the height
050     * @see #getHeight
051     */
052        public void setHeight(float height) {
053                this.height = height;
054        }
055
056        /**
057     * Get the height of the arc.
058     * @return the height
059     * @see #setHeight
060     */
061        public float getHeight() {
062                return height;
063        }
064
065        /**
066     * Set the angle of the arc.
067     * @param angle the angle of the arc.
068     * @angle
069     * @see #getAngle
070     */
071        public void setAngle(float angle) {
072                this.angle = angle;
073        }
074
075        /**
076     * Returns the angle of the arc.
077     * @return the angle of the arc.
078     * @see #setAngle
079     */
080        public float getAngle() {
081                return angle;
082        }
083
084        /**
085     * Set the spread angle of the arc.
086     * @param spreadAngle the angle
087     * @angle
088     * @see #getSpreadAngle
089     */
090        public void setSpreadAngle(float spreadAngle) {
091                this.spreadAngle = spreadAngle;
092        }
093
094        /**
095     * Get the spread angle of the arc.
096     * @return the angle
097     * @angle
098     * @see #setSpreadAngle
099     */
100        public float getSpreadAngle() {
101                return spreadAngle;
102        }
103
104        /**
105         * Set the radius of the effect.
106         * @param radius the radius
107     * @min-value 0
108     * @see #getRadius
109         */
110        public void setRadius(float radius) {
111                this.radius = radius;
112        }
113
114        /**
115         * Get the radius of the effect.
116         * @return the radius
117     * @see #setRadius
118         */
119        public float getRadius() {
120                return radius;
121        }
122
123        /**
124         * Set the centre of the effect in the Y direction as a proportion of the image size.
125         * @param centreX the center
126     * @see #getCentreX
127         */
128        public void setCentreX( float centreX ) {
129                this.centreX = centreX;
130        }
131
132        /**
133         * Get the centre of the effect in the X direction as a proportion of the image size.
134         * @return the center
135     * @see #setCentreX
136         */
137        public float getCentreX() {
138                return centreX;
139        }
140        
141        /**
142         * Set the centre of the effect in the Y direction as a proportion of the image size.
143         * @param centreY the center
144     * @see #getCentreY
145         */
146        public void setCentreY( float centreY ) {
147                this.centreY = centreY;
148        }
149
150        /**
151         * Get the centre of the effect in the Y direction as a proportion of the image size.
152         * @return the center
153     * @see #setCentreY
154         */
155        public float getCentreY() {
156                return centreY;
157        }
158        
159        /**
160         * Set the centre of the effect as a proportion of the image size.
161         * @param centre the center
162     * @see #getCentre
163         */
164        public void setCentre( Point2D centre ) {
165                this.centreX = (float)centre.getX();
166                this.centreY = (float)centre.getY();
167        }
168
169        /**
170         * Get the centre of the effect as a proportion of the image size.
171         * @return the center
172     * @see #setCentre
173         */
174        public Point2D getCentre() {
175                return new Point2D.Float( centreX, centreY );
176        }
177        
178    public BufferedImage filter( BufferedImage src, BufferedImage dst ) {
179                iWidth = src.getWidth();
180                iHeight = src.getHeight();
181                icentreX = iWidth * centreX;
182                icentreY = iHeight * centreY;
183                iWidth--;
184                return super.filter( src, dst );
185        }
186        
187        protected void transformInverse(int x, int y, float[] out) {
188                float dx = x-icentreX;
189                float dy = y-icentreY;
190                float theta = (float)Math.atan2( -dy, -dx ) + angle;
191                float r = (float)Math.sqrt( dx*dx + dy*dy );
192
193                theta = ImageMath.mod( theta, 2*(float)Math.PI );
194
195                out[0] = iWidth * theta/(spreadAngle+0.00001f);
196                out[1] = iHeight * (1-(r-radius)/(height+0.00001f));
197        }
198
199        public String toString() {
200                return "Distort/Circle...";
201        }
202
203}