Mobile UI Experiences

Tag: demoscene

Image Rotation in j2me

by raimon on Aug.26, 2009, under j2me

Lately I’ve been creating some low level image functions for Java ME just to see if low level bitmap manipulation was way too slow for doing it on real time on Java ME or it was, at least, usable. I’ll publish more functions but I’ll start with Image Rotation.

In Java ME is easy to rotate images if you want to rotate by an angle multiple of 90° but it doesn’t provide any mechanism to rotate it by an arbitrary angle (yes, ok… you could do the same using the Mobile 3D API)

I created a small function that fills that gap and allows image rotation by any angle. The resulting image will have the same size as the original (watch out for the corners..)

  1. public static void rotateImage(Image src, float angle, Graphics g) {
  2.     int sw = src.getWidth();
  3.     int sh = src.getHeight();
  4.     int[] srcData = new int[sw * sh];
  5.  
  6.     src.getRGB(srcData, 0, sw, 0, 0, sw, sh);
  7.     int[] dstData = new int[sw * sh];
  8.  
  9.     double rads = angle * Math.PI / 180.f;
  10.     float sa = (float) Math.sin(rads);
  11.     float ca = (float) Math.cos(rads);
  12.     int isa = (int) (256 * sa);
  13.     int ica = (int) (256 * ca);
  14.  
  15.     int my = - (sh >> 1);
  16.     for(int i = 0; i < sh; i++) {
  17.         int mx = - (sw  >> 1);
  18.         for(int j = 0; j < sw; j++) {
  19.             int srcx = ( mx * ica + my * isa) >> 8;
  20.             int srcy = (-mx * isa + my * ica) >> 8;
  21.  
  22.             srcx += sw >> 1;
  23.             srcy += sh >> 1;
  24.  
  25.             if(srcx < 0) srcx = 0;
  26.             if(srcy < 0) srcy = 0;
  27.             if(srcx > sw - 1) srcx = sw - 1;
  28.             if(srcy > sh - 1) srcy = sh - 1;
  29.  
  30.             dstData[j + i * sw] = srcData[srcx + srcy * sw];
  31.  
  32.             mx++;
  33.         }
  34.         my++;
  35.     }
  36.  
  37.     g.drawRGB(dstData, 0, sw, 0, 0, sw, sh, true);
  38. }

If we move all the calculations that doesn’t need to be done in the inner loop to the external loop we will have a speed improvement:

  1. public static void rotateImage(Image src, float angle, Graphics g) {
  2.     int sw = src.getWidth();
  3.     int sh = src.getHeight();
  4.     int[] srcData = new int[sw * sh];
  5.  
  6.     src.getRGB(srcData, 0, sw, 0, 0, sw, sh);
  7.     int[] dstData = new int[sw * sh];
  8.  
  9.     double rads = angle * Math.PI / 180.f;
  10.     float sa = (float) Math.sin(rads);
  11.     float ca = (float) Math.cos(rads);
  12.     int isa = (int) (256 * sa);
  13.     int ica = (int) (256 * ca);
  14.  
  15.     int my = - (sh >> 1);
  16.     for(int i = 0; i < sh; i++) {
  17.         int wpos = i * sw;
  18.  
  19.         int xacc = my * isa - (sw >> 1) * ica + ((sw >> 1) << 8);
  20.         int yacc = my * ica + (sw >> 1) * isa + ((sh >> 1) << 8);
  21.  
  22.         for(int j = 0; j < sw; j++) {
  23.             int srcx = (xacc >> 8);
  24.             int srcy = (yacc >> 8);
  25.  
  26.             if(srcx < 0) srcx = 0;
  27.             if(srcy < 0) srcy = 0;
  28.             if(srcx > sw - 1) srcx = sw - 1;
  29.             if(srcy > sh - 1) srcy = sh - 1;
  30.  
  31.             dstData[wpos++] = srcData[srcx + srcy * sw];
  32.  
  33.             xacc += ica;
  34.             yacc -= isa;
  35.         }
  36.         my++;
  37.     }
  38.  
  39.     g.drawRGB(dstData, 0, sw, 0, 0, sw, sh, true);
  40. }

And if we know beforehand the size of the image we want to rotate we could do some extra tricks (for example, here assumes the source image will be 256×256 pixels and will only work with that resolution):

  1. public static void rotateImage(Image src, float angle, Graphics g) {
  2.     int sw = src.getWidth();
  3.     int sh = src.getHeight();
  4.     int[] srcData = new int[sw * sh];
  5.  
  6.     src.getRGB(srcData, 0, sw, 0, 0, sw, sh);
  7.     int[] dstData = new int[sw * sh];
  8.  
  9.     double rads = angle * Math.PI / 180.f;
  10.     float sa = (float) Math.sin(rads);
  11.     float ca = (float) Math.cos(rads);
  12.     int isa = (int) (256 * sa);
  13.     int ica = (int) (256 * ca);
  14.  
  15.     int my = - (sh >> 1);
  16.     for(int i = 0; i < sh; i++) {
  17.         int wpos = i * sw;
  18.  
  19.         int xacc = my * isa - (sw >> 1) * ica + ((sw >> 1) << 8);
  20.         int yacc = my * ica + (sw >> 1) * isa + ((sh >> 1) << 8);
  21.  
  22.         for(int j = 0; j < sw; j++) {
  23.             int srcx = (xacc >> 8) & 0xff;
  24.             int srcy = yacc & 0xff00;
  25.  
  26.             dstData[wpos++] = srcData[srcx + srcy];
  27.  
  28.             xacc += ica;
  29.             yacc -= isa;
  30.         }
  31.         my++;
  32.     }
  33.  
  34.     g.drawRGB(dstData, 0, sw, 0, 0, sw, sh, true);
  35. }

These functions paints the rotated image in a Graphics object directly, but doing some minor changes it could generate a new Image with the content:
* Change the function declaration to:

  1. public static Image rotateImage_img(Image src, float angle) {

* Replace the drawRGB call with:

  1. return Image.createRGBImage(dstData, sw, sh, true);

Feel free to use it for whatever you want but it would be nice if you drop me a line and put me somewhere in the credits :)

4 Comments :, , more...

Move along, nothing to see here..

by raimon on Apr.24, 2008, under j2me

In this blog I’ll post the experiences of working developing J2ME applications. It will be mainly focused on the graphical part and how the user may interact with them although there will be non-interactive applications like the one I’m introducing below.
This was my first attempt to do a 4k intro with J2ME. I’m not proud of the result, but it was made only in one afternoon to increase dramatically the number of compo entries (from 1 to 2). The binary application requires a J2ME Phone with MMAPI + JSR 184 support. In order to install the application you have to send the mtro.jar file to your phone through bluetooth / cable / irda.

mtro

Binary

Comments Off :, , more...

Looking for something?

Use the form below to search the site:

Still not finding what you're looking for? Drop a comment on a post or contact us so we can take care of it!

Links!

    Archives

    All entries, chronologically...