How to rotate a image in Java
A coordinate transformation can be applied to the Graphics2D object.
// gr is a java.awt.Graphics2D object java.awt.geom.AffineTransform transform = gr.getTransform(); // rotate the image about the center of panel. int xPanelCenter=this.getWidth()/2; int yPanelCenter=this.getHeight()/2; double pi=3.141592654; double angle=rotatedDegree*pi/180; // convert to radian transform.rotate(angle,xPanelCenter,yPanelCenter); gr.setTransform(transform); // apply transformation
At this point, all coordinates in the gr object will be transformed. Calling the drawImage() method now will draw a transformed (rotated) image.
// draw the image gr.drawImage(taichiImage,10,10,this);
How to create an animation thread
To create a new thread in Java, you must specified the thread entry point, which is typically know as the "run()" method.
Steps to start a running thread :
- Implements the run() method of a "Runnable" interface.
- Wrap the Runnable interface with a Thread object.
- Invoke the start() method of the Thread object.
Let's do it step by step now.
- Implements the run() method of a "Runnable" interface.
- Wrap the Runnable interface with a Thread object.
- Invoke the start() method of the Thread object.
// animation thread
public void run()
{
while (true)
{
rotatedDegree=rotatedDegree+1; // rotate one degree for each frame.
repaint();
// sleep for 40 ms, roughly 25 frames per second (1000/40=25)
try { Thread.sleep(40); } catch (Exception ignore) {}
}
}
/*
The idea of the above animation is : repeatedly draw a new frame, repaint the screen
then delay for a while so that the frame can be seen.
To create a smooth animation, frame per second should between 20 and 30.
The above sample has a FPS value slightly less than 25.
*/
// graphicsPanel is a Runnable interface Thread thread=new Thread(graphicsPanel);
thread.start(); // the run() method will be started
Full runnable demo
/******************************************************************************
* File : RotatingTaichi.java
* Author : http://java.macteki.com/
* Description :
* Display a rotating Taichi image in a graphics panel.
* Tested with : JDK 1.6
******************************************************************************/
import java.awt.image.BufferedImage;
import java.awt.Point;
class RotatingTaichi extends javax.swing.JPanel implements Runnable
{
private BufferedImage taichiImage;
private int rotatedDegree=0;
public static RotatingTaichi getInstance()
{
RotatingTaichi panel=new RotatingTaichi();
panel.setPreferredSize(new java.awt.Dimension(320,320));
panel.setBackground(java.awt.Color.WHITE);
panel.taichiImage = new BufferedImage(300,300,BufferedImage.TYPE_INT_RGB);
panel.drawTaichi(panel.taichiImage,150,150,100);
return panel;
}
// draw a taichi image
public void drawTaichi(BufferedImage image,int xCenter,int yCenter, int radius)
{
java.awt.Graphics2D gr = (java.awt.Graphics2D) image.getGraphics();
gr.setColor(java.awt.Color.WHITE);
gr.fillRect(0,0,image.getWidth(this),image.getWidth(this));
gr.setStroke(new java.awt.BasicStroke(2)); // pen width
gr.setColor(java.awt.Color.BLACK);
// draw the big circle
int r=radius; // radius
int xc=xCenter, yc=yCenter; // center
// the bounding rectangle (x,y,w,h) of the circle is defined by :
// x=xc-r, y=yc-r, w=r*2, h=r*2;
gr.drawArc(xc-r,yc-r,r*2,r*2,0,360); // (x,y,w,h,startDegree,arcDegree)
// draw a half circle inside the big circle
xc=xCenter; yc=yCenter-radius/2; r=radius/2;
gr.drawArc(xc-r,yc-r,r*2,r*2,270,180); // (x,y,w,h,startDegree,arcDegree)
// draw another half circle inside the big circle
xc=xCenter; yc=yCenter+radius/2; r=radius/2;
gr.drawArc(xc-r,yc-r,r*2,r*2,90,180); // (x,y,w,h,startDegree,arcDegree)
// draw two more small circles
xc=xCenter; yc=yCenter-radius/2; r=radius/8;
gr.drawArc(xc-r,yc-r,r*2,r*2,0,360); // (x,y,w,h,startDegree,arcDegree)
xc=xCenter; yc=yCenter+radius/2; r=radius/8+1;
gr.drawArc(xc-r,yc-r,r*2,r*2,0,360); // (x,y,w,h,startDegree,arcDegree)
// fill with appropriate color
int black=packRgb(0,0,0);
floodFill(image,xCenter,yCenter-radius/2,black);
floodFill(image,xCenter,yCenter+radius/16,black);
}
// override the paint method
// just paint the taichi image here
public void paintComponent(java.awt.Graphics graphics)
{
super.paintComponent(graphics);
// Graphics2D is a better choice to the default Graphics object
java.awt.Graphics2D gr=(java.awt.Graphics2D) graphics;
java.awt.geom.AffineTransform transform = gr.getTransform();
// rotate the image about the center of panel.
int xPanelCenter=this.getWidth()/2;
int yPanelCenter=this.getHeight()/2;
double pi=3.141592654;
double angle=rotatedDegree*pi/180; // convert to radian
transform.rotate(angle,xPanelCenter,yPanelCenter);
gr.setTransform(transform);
gr.drawImage(taichiImage,10,10,this);
}
public static int packRgb(int r,int g,int b)
{
return (r*256+g)*256+b;
}
// implements the flood fill algorithm
public static void floodFill(BufferedImage image, int x,int y, int fillColor)
{
java.util.ArrayList<Point> examList=new java.util.ArrayList<Point>();
int initialColor=image.getRGB(x,y);
examList.add(new Point(x,y));
while (examList.size()>0)
{
Point p = examList.remove(0); // get and remove the first point in the list
if (image.getRGB(p.x,p.y)==initialColor)
{
x = p.x; y = p.y;
image.setRGB(x, y, fillColor); // fill current pixel
if (image.getRGB(x-1,y)==initialColor) // check west neighbor
{
examList.add(new Point(x-1,y));
}
if (image.getRGB(x+1,y)==initialColor) // check east neighbor
{
examList.add(new Point(x+1,y));
}
if (image.getRGB(x,y-1)==initialColor) // check north neighbor
{
examList.add(new Point(x,y-1));
}
if (image.getRGB(x,y+1)==initialColor) // check south neighbor
{
examList.add(new Point(x,y+1));
}
}
}
}
// animation thread
public void run()
{
while (true)
{
rotatedDegree=rotatedDegree+1; // rotate one degree for each frame.
repaint();
// sleep for 40 ms, roughly 25 frames per second (1000/40=25)
try { Thread.sleep(40); } catch (Exception ignore) {}
}
}
public static void main(String[] args) throws Exception
{
RotatingTaichi graphicsPanel = RotatingTaichi.getInstance();
javax.swing.JFrame window=new javax.swing.JFrame();
window.add(graphicsPanel);
window.pack();
window.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
window.setTitle("Macteki Taichi Panel");
window.setVisible(true);
// start the animation thread
new Thread(graphicsPanel).start();
}
}
Thanks for reading. Comments are welcome.
No comments:
Post a Comment