| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- /*
- ** Copyright 2005 Huxtable.com. All rights reserved.
- */
- package com.cvte.blurfilter;
- import java.awt.*;
- import java.awt.geom.*;
- import java.awt.image.*;
- public class MotionBlurOp extends AbstractBufferedImageOp {
- private float centreX = 0.5f, centreY = 0.5f;
- private float distance;
- private float angle;
- private float rotation;
- private float zoom;
- public MotionBlurOp() {
- }
-
- public MotionBlurOp( float distance, float angle, float rotation, float zoom ) {
- this.distance = distance;
- this.angle = angle;
- this.rotation = rotation;
- this.zoom = zoom;
- }
-
- public void setAngle( float angle ) {
- this.angle = angle;
- }
- public float getAngle() {
- return angle;
- }
-
- public void setDistance( float distance ) {
- this.distance = distance;
- }
- public float getDistance() {
- return distance;
- }
-
- public void setRotation( float rotation ) {
- this.rotation = rotation;
- }
- public float getRotation() {
- return rotation;
- }
-
- public void setZoom( float zoom ) {
- this.zoom = zoom;
- }
- public float getZoom() {
- return zoom;
- }
-
- public void setCentreX( float centreX ) {
- this.centreX = centreX;
- }
- public float getCentreX() {
- return centreX;
- }
-
- public void setCentreY( float centreY ) {
- this.centreY = centreY;
- }
- public float getCentreY() {
- return centreY;
- }
-
- public void setCentre( Point2D centre ) {
- this.centreX = (float)centre.getX();
- this.centreY = (float)centre.getY();
- }
- public Point2D getCentre() {
- return new Point2D.Float( centreX, centreY );
- }
-
- private int log2( int n ) {
- int m = 1;
- int log2n = 0;
- while (m < n) {
- m *= 2;
- log2n++;
- }
- return log2n;
- }
- public BufferedImage filter( BufferedImage src, BufferedImage dst ) {
- if ( dst == null )
- dst = createCompatibleDestImage( src, null );
- BufferedImage tsrc = src;
- float cx = (float)src.getWidth() * centreX;
- float cy = (float)src.getHeight() * centreY;
- float imageRadius = (float)Math.sqrt( cx*cx + cy*cy );
- float translateX = (float)(distance * Math.cos( angle ));
- float translateY = (float)(distance * -Math.sin( angle ));
- float scale = zoom;
- float rotate = rotation;
- float maxDistance = distance + Math.abs(rotation*imageRadius) + zoom*imageRadius;
- int steps = log2((int)maxDistance);
- translateX /= maxDistance;
- translateY /= maxDistance;
- scale /= maxDistance;
- rotate /= maxDistance;
-
- if ( steps == 0 ) {
- Graphics2D g = dst.createGraphics();
- g.drawRenderedImage( src, null );
- g.dispose();
- return dst;
- }
-
- BufferedImage tmp = createCompatibleDestImage( src, null );
- for ( int i = 0; i < steps; i++ ) {
- Graphics2D g = tmp.createGraphics();
- g.drawImage( tsrc, null, null );
- g.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON );
- g.setRenderingHint( RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR );
- g.setComposite( AlphaComposite.getInstance( AlphaComposite.SRC_OVER, 0.5f ) );
- g.translate( cx+translateX, cy+translateY );
- g.scale( 1.0001+scale, 1.0001+scale ); // The .0001 works round a bug on Windows where drawImage throws an ArrayIndexOutofBoundException
- if ( rotation != 0 )
- g.rotate( rotate );
- g.translate( -cx, -cy );
- g.drawImage( dst, null, null );
- g.dispose();
- BufferedImage ti = dst;
- dst = tmp;
- tmp = ti;
- tsrc = dst;
- translateX *= 2;
- translateY *= 2;
- scale *= 2;
- rotate *= 2;
- }
- return dst;
- }
-
- public String toString() {
- return "Blur/Motion Blur...";
- }
- }
|