Welcome to rednebula.com
This is the personal site of Bjarne Fich.
Site formerly known as "www.dragonslayer.dk"
Optimized for
Get Firefox!

A rotating java applet image
Some time ago I started to play with making applets. Mostly to do small games. But one feature I missed was the ability to rotate images. Swing do have some features to do so, but I decided to make my own.

I started by searching a bit on the internet to see if I could find some applet code that did rotate an image. I found a piece that could flip the image, so the rest was fairly simple. Rather than doing a fixed transformation, I now do a transformation based upon a simple cos/sin function.

I also split the code into two sections, one to initialize the rotations function and one to do the actual rotation.

Then I added the basic applet stuff (back drawing to avoid flickering) and a timer to handle the example.

In the example I draw the gif 3 times. One is a stationary image and the second is rotating clockwise, without clearing its background, thereby causing it to make trails, while the third is rotating counter-clockwise without trails (clearing the background before drawing).

You can see the example here
//
// Rotating image
//
// Made by Bjarne Fich - Feb 2008
// Feel free to copy but keep reference
//
// Inspired by: http://www.rgagnon.com/javadetails/java-0248.html
//

import java.applet.Applet;
import java.awt.Image;
import java.awt.Graphics;
import java.awt.MediaTracker;
import java.awt.Color;
import java.awt.image.PixelGrabber;
import java.awt.image.MemoryImageSource;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import javax.swing.Timer;

public class rotateImage extends Applet implements Runnable {
  int imgSize = 0;
  Image rotImage = null;
  int buffer[] = null;
  int rotate[] = null;
  int rotation = 0;

  Timer timer = null;

  int width, height;
  Image myImage = null;

  Image backBuffer;
  Graphics backGraphics;

  // ****************************
  //    Rotation
  // ****************************

  // Initializes the rotation functions
  // Uses: myImage
  // Sets: imgSize, buffer, rotate
  public void initRotate() {
    if (myImage == null) return;

    try {
      MediaTracker tracker = new MediaTracker (this);
      tracker.addImage (myImage, 0);
      tracker.waitForAll();
    } catch(Exception e) {
      e.printStackTrace();
    }

    imgSize = myImage.getWidth(this) < myImage.getHeight(this)
    	? myImage.getHeight(this) : myImage.getWidth(this);
    buffer = new int[imgSize * imgSize];
    rotate = new int[imgSize * imgSize];

    try {
      PixelGrabber grabber = new PixelGrabber(myImage, 0, 0, imgSize, imgSize, buffer, 0, imgSize);
      try {
        grabber.grabPixels();
      } catch(InterruptedException e) {
        e.printStackTrace();
      }
    } catch(Exception e) {
      e.printStackTrace();
    }
  }

  // Do the rotation
  // Uses: myImage, imgSize, buffer, rotate
  // Sets: rotImage
  public boolean doRotate(int ang) {
    if (buffer != null) {
      try {
        double cos = Math.cos((double)(ang)*2*Math.PI/360.0);
        double sin = Math.sin((double)(ang)*2*Math.PI/360.0);
        double ds2 = (double)(imgSize) / 2;
        for(int x = 0; x < imgSize; x++) {
          for(int y = 0; y < imgSize; y++) {
            double dx = (double)(x) - ds2;
            double dy = (double)(y) - ds2;
            int xx = (int)(cos*dx+sin*dy) + myImage.getWidth(this) / 2;
            int yy = (int)(-sin*dx+cos*dy) + myImage.getHeight(this) / 2;
            xx = ((xx<0) ? (0) : ((xx >= imgSize) ? (imgSize-1) : (xx)));
            yy = ((yy<0) ? (0) : ((yy >= imgSize) ? (imgSize-1) : (yy)));
            rotate[(y*imgSize)+x] = buffer[(yy*imgSize)+xx];
          }
        }
        rotImage = createImage(new MemoryImageSource(imgSize, imgSize, rotate, 0, imgSize));
        return true;
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
    return false;
  }

  // ****************************
  //    Timer ticker
  // ****************************

  ActionListener timerTicker = new ActionListener() {
    public void actionPerformed(ActionEvent evt) {
      rotation++;
    }
  };

  // ****************************
  //    Init, start and stop
  // ****************************

  public void init() {
    if(this.getParameter("width") != null) {
      width = Integer.parseInt(this.getParameter("width"));
    } else {
      width = 400;
    }
    if(this.getParameter("height") != null) {
      height = Integer.parseInt(this.getParameter("height"));
    } else {
      height = 400;
    }

    myImage = getImage(getDocumentBase(), "dragon.gif");

    backBuffer = createImage(width, height);
    backGraphics = backBuffer.getGraphics();
    backGraphics.setColor(Color.white);

    initRotate();
  }

  public void start() {
    if (timer == null) {
      timer = new Timer(10, timerTicker);
      timer.start();
    }
  }

  public void stop() {
    if (timer != null) {
      timer.stop();
      timer = null;
    }
  }

  public void run() {
  }

  // ****************************
  //   Drawing and backbuffer
  // ****************************

  public void update(Graphics g) {
    if (myImage == null) return;

    // Draw the first stationary gif
    backGraphics.drawImage(myImage, width/6-myImage.getWidth(this)/2,
    	height/2-myImage.getHeight(this)/2, this);

    // Draw the second rotating gif with trails
    if (doRotate(-rotation)) {
      backGraphics.drawImage(rotImage, width/2-imgSize/2, height/2-imgSize/2, this);
    }

    // Draw the third rotating gif (clear background)
    if (doRotate(rotation)) {
      backGraphics.setColor(Color.white);
      backGraphics.fillRect(width*5/6-imgSize/2, height/2-imgSize/2, imgSize, imgSize);
      backGraphics.drawImage(rotImage, width*5/6-imgSize/2, height/2-imgSize/2, this);
    }

    g.drawImage(backBuffer, 0, 0, this);
  }

  public void paint(Graphics g) {
    update(g);
  }
}
Contact