160 lines
5.7 KiB
Java
160 lines
5.7 KiB
Java
|
import java.awt.*;
|
||
|
import java.awt.geom.*;
|
||
|
import java.util.Timer;
|
||
|
import java.util.TimerTask;
|
||
|
import java.awt.image.BufferedImage;
|
||
|
|
||
|
/**
|
||
|
* A simple example for transforming one triangulated image into another one.
|
||
|
* For the animation, the doube buffering technique is applied in the same way
|
||
|
* as in the clock example in the class DoubeBufferingClockExample.
|
||
|
*
|
||
|
* @author Frank Klawonn
|
||
|
* Last change 31.05.2005
|
||
|
*
|
||
|
* @see TriangulatedImage
|
||
|
* @see BufferImageDrawer
|
||
|
* @see DoubeBufferingClockExample
|
||
|
*/
|
||
|
public class MorphingCandS extends TimerTask
|
||
|
{
|
||
|
|
||
|
//The window in which the transformation is shown.
|
||
|
private BufferedImageDrawer buffid;
|
||
|
|
||
|
//The two images to be transformed into each other will be scaled to
|
||
|
//this size.
|
||
|
private int width;
|
||
|
private int height;
|
||
|
|
||
|
//The number of steps (frames) for the transformation.
|
||
|
private int steps;
|
||
|
|
||
|
//The first triangulated image.
|
||
|
private TriangulatedImage t1;
|
||
|
|
||
|
//The second triangulated image.
|
||
|
private TriangulatedImage t2;
|
||
|
|
||
|
//This is used for generating/storing the intermediate images.
|
||
|
private BufferedImage mix;
|
||
|
|
||
|
//A variable which is increased stepwise from 0 to 1. It is needed
|
||
|
//for the computation of the convex combinations.
|
||
|
private double alpha;
|
||
|
|
||
|
//The change of alpha in each step: deltAlpha = 1.0/steps
|
||
|
private double deltaAlpha;
|
||
|
|
||
|
|
||
|
/**
|
||
|
* Constructor
|
||
|
*
|
||
|
* @param bid The window in which the transformation is shown.
|
||
|
*/
|
||
|
MorphingCandS(BufferedImageDrawer bid)
|
||
|
{
|
||
|
buffid = bid;
|
||
|
width = 100;
|
||
|
height = 150;
|
||
|
steps = 100;
|
||
|
deltaAlpha = 1.0/steps;
|
||
|
alpha = 0;
|
||
|
//This object is used for loading the two images.
|
||
|
Image loadedImage;
|
||
|
//Generating the first triangulated image:
|
||
|
t1 = new TriangulatedImage();
|
||
|
//Define the size.
|
||
|
t1.bi = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
|
||
|
//Generate the Graphics2D object.
|
||
|
Graphics2D g2dt1 = t1.bi.createGraphics();
|
||
|
//Load the image and draw it on the corresponding BufferedImage.
|
||
|
loadedImage = new javax.swing.ImageIcon("image1.jpg").getImage();
|
||
|
g2dt1.drawImage(loadedImage,0,0,null);
|
||
|
//Definition of the points for the triangulation.
|
||
|
t1.tPoints = new Point2D[9];
|
||
|
t1.tPoints[0] = new Point2D.Double(0,0);
|
||
|
t1.tPoints[1] = new Point2D.Double(0,110);
|
||
|
t1.tPoints[2] = new Point2D.Double(0,150);
|
||
|
t1.tPoints[3] = new Point2D.Double(50,150);
|
||
|
t1.tPoints[4] = new Point2D.Double(100,150);
|
||
|
t1.tPoints[5] = new Point2D.Double(100,110);
|
||
|
t1.tPoints[6] = new Point2D.Double(100,0);
|
||
|
t1.tPoints[7] = new Point2D.Double(50,0);
|
||
|
t1.tPoints[8] = new Point2D.Double(50,110);
|
||
|
//Definition of the triangles.
|
||
|
t1.triangles = new int[8][3];
|
||
|
for (int i=0; i<7; i++)
|
||
|
{
|
||
|
t1.triangles[i][0] = i;
|
||
|
t1.triangles[i][1] = i+1;
|
||
|
t1.triangles[i][2] = 8;
|
||
|
}
|
||
|
t1.triangles[7][0] = 7;
|
||
|
t1.triangles[7][1] = 0;
|
||
|
t1.triangles[7][2] = 8;
|
||
|
//The same for the second image.
|
||
|
t2 = new TriangulatedImage();
|
||
|
t2.bi = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
|
||
|
Graphics2D g2dt2 = t2.bi.createGraphics();
|
||
|
loadedImage = new javax.swing.ImageIcon("image2.jpg").getImage();
|
||
|
g2dt2.drawImage(loadedImage,0,0,null);
|
||
|
t2.tPoints = new Point2D[9];
|
||
|
t2.tPoints[0] = new Point2D.Double(0,0);
|
||
|
t2.tPoints[1] = new Point2D.Double(0,40);
|
||
|
t2.tPoints[2] = new Point2D.Double(0,150);
|
||
|
t2.tPoints[3] = new Point2D.Double(55,150);
|
||
|
t2.tPoints[4] = new Point2D.Double(100,150);
|
||
|
t2.tPoints[5] = new Point2D.Double(100,40);
|
||
|
t2.tPoints[6] = new Point2D.Double(100,0);
|
||
|
t2.tPoints[7] = new Point2D.Double(55,0);
|
||
|
t2.tPoints[8] = new Point2D.Double(55,40);
|
||
|
//The indexing for the triangles must be the same as in the
|
||
|
//the first image.
|
||
|
t2.triangles = t1.triangles;
|
||
|
}
|
||
|
|
||
|
|
||
|
//This method is called in regular intervals. This method computes
|
||
|
//the updated image/frame and calls the repaint method to draw the
|
||
|
//updated image on the window.
|
||
|
public void run()
|
||
|
{
|
||
|
//Since this method is called arbitrarily often, interpolation must only
|
||
|
//be carred out while alpha is between 0 and 1.
|
||
|
if (alpha>=0 && alpha<=1)
|
||
|
{
|
||
|
//Generate the interpolated image.
|
||
|
mix = t1.mixWith(t2,alpha);
|
||
|
//Draw the interpolated image on the BufferedImage.
|
||
|
buffid.g2dbi.drawImage(mix,50,50,null);
|
||
|
//Call the method for updating the window.
|
||
|
buffid.repaint();
|
||
|
}
|
||
|
//Increment alpha.
|
||
|
alpha = alpha+deltaAlpha;
|
||
|
}
|
||
|
|
||
|
|
||
|
public static void main(String[] argv)
|
||
|
{
|
||
|
//Width of the window.
|
||
|
int width = 200;
|
||
|
//Height of the window.
|
||
|
int height = 250;
|
||
|
//Specifies (in milliseconds) when the frame should be updated.
|
||
|
int delay = 50;
|
||
|
//The BufferedImage to be drawn in the window.
|
||
|
BufferedImage bi = new BufferedImage(width,height,BufferedImage.TYPE_INT_RGB);
|
||
|
//The window in which everything is drawn.
|
||
|
BufferedImageDrawer bid = new BufferedImageDrawer(bi,width,height);
|
||
|
bid.setTitle("Transforming shape and colour");
|
||
|
//The TimerTask in which the repeated computations for drawing take place.
|
||
|
MorphingCandS mcs = new MorphingCandS(bid);
|
||
|
Timer t = new Timer();
|
||
|
t.scheduleAtFixedRate(mcs,0,delay);
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|