20

I'm looking for an algorithm that rotates an image by some degrees (input).

public Image rotateImage(Image image, int degrees)

(Image instances could be replaced with int[] containing each pixel RGB values, My problem is that i need to implement it for a JavaME MIDP 2.0 project so i must use code runnable on JVM prior to version 1.5 Can anyone help me out with this ?

EDIT: I forgot to mention that i don't have SVG APIs available and that i need a method to rotate by arbitrary degree other than 90 - 180- 270

Also, no java.awt.* packages are available on MIDP 2.0

gnat
  • 6,213
  • 108
  • 53
  • 73
Stefano Driussi
  • 2,241
  • 1
  • 14
  • 19
  • The Sprite class gives some basic rotational and mirror of an image. However for marginal degrees, we might have to use some algorithm – Prabhu R Jun 05 '09 at 11:17

4 Answers4

25

One of the best pages describing image rotation algorithms I've found on the internet is tied to Dan Bloomberg's excellent leptonica library. While the leptonica library itself is written in C and won't help you, his page on image rotation algorithms:

http://www.leptonica.org/rotation.html

is definitely worth a read. You will most likely want to implement something like the Rotation by Area Mapping algorithm he describes in the second portion of the page.

Clonkex
  • 3,373
  • 7
  • 38
  • 55
earino
  • 2,885
  • 21
  • 20
  • It's worth noting that if you already have a simplistic rotation algorithm (such as the Rotation by Sampling one given in the link in this answer) and a good resizing algorithm, you can (I discovered) resize the image by two or four times, do the simplistic rotate, then half or quarter the image using the good resize algorithm. This is what I do in [Jimp](https://www.npmjs.com/package/jimp) to get vastly better image quality after the rotation. – Clonkex Oct 25 '22 at 21:36
7

General solution: For each pixel in the destination image, take the pixel in the source image with coordinates of the destination pixel, rotated in the opposite direction.

Enhancement to solution: The rotation usually won't give exact pixel coordinates. Do a weighted average of the source pixel with its neighbors, according to the percentage it overlaps them.

Faster solution for binary images: Convert the image into "runs" of consecutive foreground pixels. Then rotate the endpoints of these lines and draw them into the destination.

Normally this will produce slight gaps due to integer roundoff, so when one or both endpoints are more than 10% away from an integer, patch by drawing TWO lines for the single source line, using the integer coordinates rounded up and down.

If one endpoint is within 10% and the other isn't, the two lines will form a 'V' shape. If both are off by more than 10%, the two lines will form an 'X' shape.

This can be done with respect to the X axis or the Y axis . Use the one with the smallest angle between the axis and the rotation angle. (I.e. if the rotation angle is between 45 and -45, use the X axis.)

Still faster solution for binary images: If there are fewer background pixels than foreground pixels, fill the destination with foreground, and follow the above algorithm with background pixels.

user20493
  • 5,704
  • 7
  • 34
  • 31
-2
  public Image rotateImage(Image img, float degrees){
   BufferedImage sourceBI = new BufferedImage(img.getWidth(null),img.getHeight(null),BufferedImage.TYPE_INT_ARGB);
   sourceBI.getGraphics().drawImage(img,0,0,null);
   AffineTransform at = new AffineTransform();
   at.rotate(degrees*Math.PI/180, sourceBI.getWidth()/2, sourceBI.getHeight()/2);
   BufferedImageOp bio = new AffineTransformOp(at, AffineTransformOp.TYPE_BILINEAR);
   return bio.filter(sourceBI, null);
  }
dplass
  • 1,463
  • 10
  • 20
dave
  • 15
  • 1
    there's no `BufferedImage` nor `AffineTransform` in java me [MIDP API](http://download.oracle.com/javame/config/cldc/ref-impl/midp2.0/jsr118/index.html) – gnat Sep 17 '11 at 10:32
-2

Graphics2D and AffineTransform will help you do exactly what you want. Specifically, Graphics2D.drawImage(Image, AffineTransform) and AffineTransform.getRotateInstance. You can also do scaling, translation, and shearing with this. Both classes have been in the runtime since at least 1.4 probably earlier.

basszero
  • 29,624
  • 9
  • 57
  • 79