- Hi everybody.
I've been trying to rotate an image for a few days without success. I searched other forums as well but still did not found what i wanted.
So can someone please create a tiny program that rotates a bitmap at any given angle.
Thanks very much.11-06-10 09:49 AMLike 0 -
- What exactly are you trying to do that a PC/Mac can't do?
I have the following method:
Code:public static Bitmap rotateImage(Bitmap oldB, int angle) throws Exception { int w = oldB.getWidth(); int h = oldB.getHeight(); double angRad = (angle % 360)*(Math.PI/180); Bitmap newB = new Bitmap(w,h); int[] oldD = new int[w*h]; int[] newD = new int[w*h]; oldB.getARGB(oldD, 0, w, 0, 0, w, h); int axisX = w/2; int axisY = h/2; for(int x = 0; x < oldD.length; x++) { int oldX = x%w; int oldY = x/w; int op = oldX-axisX; int adj = oldY-axisY; double oldT = MathUtilities.atan2(op, adj); double rad = Math.sqrt((op*op)+(adj*adj)); double newT = oldT+angRad; int newX = (int)MathUtilities.round((rad*Math.sin(newT))+(double)axisX); int newY = (int)MathUtilities.round((rad*Math.cos(newT))+(double)axisY); if(newX<0||newY<0||newX>=w||newY>=h) { newD[x] = 0x00000000; } else { newD[x] = oldD[(newY*w)+newX]; } } newB.setARGB(newD, 0, w, 0, 0, w, h); return newB; }
Code:rotateImage(givenImage, 90);
Thanks very much.11-06-10 03:28 PMLike 0 - let me ask my question again:
I have the following method:
Code:public static Bitmap rotateImage(Bitmap oldB, int angle) throws Exception { int w = oldB.getWidth(); int h = oldB.getHeight(); double angRad = (angle % 360)*(Math.PI/180); Bitmap newB = new Bitmap(w,h); int[] oldD = new int[w*h]; int[] newD = new int[w*h]; oldB.getARGB(oldD, 0, w, 0, 0, w, h); int axisX = w/2; int axisY = h/2; for(int x = 0; x < oldD.length; x++) { int oldX = x%w; int oldY = x/w; int op = oldX-axisX; int adj = oldY-axisY; double oldT = MathUtilities.atan2(op, adj); double rad = Math.sqrt((op*op)+(adj*adj)); double newT = oldT+angRad; int newX = (int)MathUtilities.round((rad*Math.sin(newT))+(double)axisX); int newY = (int)MathUtilities.round((rad*Math.cos(newT))+(double)axisY); if(newX<0||newY<0||newX>=w||newY>=h) { newD[x] = 0x00000000; } else { newD[x] = oldD[(newY*w)+newX]; } } N newB.setARGB(newD, 0, w, 0, 0, w, h); return newB; }
Code:rotateImage(givenImage, 90);
Thanks very much.11-06-10 03:42 PMLike 0 - There's no reason to get into all that if you just want to rotate by right angles. Just copy rows to columns, and use nested Y and X loops instead of wasting time doing modulo and division, they're slow. Counting down instead of up is also faster since you're comparing to 0 instead of a variable. To rotate by any angle, you'd have to do cubic or at least linear interpolation instead of rounding to nearest, or it will be full of aliasing distortion. Too tired right now to figure out why what you have is doing nothing, have you tried stepping through?
Last edited by LSphone; 11-07-10 at 01:56 AM.
11-07-10 01:46 AMLike 0 - right, here is the complete code. there are two java files and one image:
Code:/** * AnimationScreen.java * * Author: Mark Sohm * */ package com.msohm.animationDemo; import net.rim.device.api.system.Bitmap; import net.rim.device.api.ui.container.FullScreen; import net.rim.device.api.ui.Graphics; import net.rim.device.api.system.Characters; import net.rim.device.api.ui.UiApplication; import java.util.Date; import net.rim.device.api.ui.component.Dialog; import net.rim.device.api.system.Alert; import net.rim.device.api.util.MathUtilities; //Optimized avg fps 7100 = 34, 7290 sim = 51 - this wasn't so good after all. :) //Non optimized (draw house/sun, no clearAll) avg fps 7100 = 17, 7290 sim = 51 //Non optimized (using invalidate, no _drawHouse = false) avg fps 7100 = 25, 7290 sim = 51 //Non optimized (using invalidate, no _drawHouse = false, not overriding paintBackground) avg fps 7100 = 25, 7290 sim = 51 // - but without overriding it things have to be redrawn every time. //Can't test with just using invalidate vs calling paint directly or else //the entire screen is cleared. //Optimized (using invalidate(#, #, #, #), not overriding paintBackground, no clearAll, _drawHouse/sun) // avg fps 7100 = 51, 7290 sim = 51 //Optimized using invalidate(####), using _drawHouse saves ~ 400 ms per animation vs no _drawHouse. public class AnimationScreen extends FullScreen { private final static boolean SHOW_FRAMERATE = true; //Controls the showing of the framerate dialog. //Images. private final static Bitmap brick = Bitmap.getBitmapResource("brick.png"); private int _frameNo; //The current frame number. private int _runnerXVal; //X coordinate of the runner. private int _runnerFrame; //The current frame of the runner. private boolean _currentlyAnimating; //Set to true if an animation is in progress. //Boolean variables to control what is drawn on the screen. private boolean _drawRunner; public AnimationScreen() { super(); initialize(); } //Initialize variables to their starting values. private void initialize() { _drawRunner = true; _frameNo = 0; _runnerFrame = 0; //Draw the screen in its initial state. invalidate(); } private class AnimationThread extends Thread { Date rightNow = new Date(); long animTime; int fps; int tempY = Graphics.getScreenHeight() - 50; public void run() { int count; //Sleep 50ms to allow the invalidate method in the initialize method to fully execute. //This ensures that the screen is fully redrawn in its initial state before //this thread starts modifying drawing values, otherwise we'll see frames out of sync. try { sleep(50); } catch (Exception ex) { System.out.println("Couldn't sleep!"); } //Get the start time for the animation (FPS timer). animTime = rightNow.getTime(); _frameNo = 0; UiApplication.getUiApplication().invokeAndWait(new Runnable() { public void run() { //We want to clear the entire screen so call invalidate //instead of invalidate(#, #, #, #). invalidate(); ++_frameNo; } }); //Draw the house with the door open. //We don't need to obtain an event lock when using invalidate(#, #, #, #); invalidate(170, tempY, 5, 40); //Draw the person running out of the house. _drawRunner = true; //If show framerate is enabled calculate and display //the freamrate. if(SHOW_FRAMERATE) { //Reset the time. rightNow = new Date(); //Calculate the number of seconds the animation animated for. //We selpt for 2710 ms so subtract that value from the total time. animTime = (rightNow.getTime() - animTime) - 2910; //Ensure we don't divide by 0. if ((animTime / 1000) > 0) { //If the animation took longer than a second, calculate it. fps = (int)(_frameNo / (animTime / 1000)); } else { //Otherwise assume 1 second. fps = _frameNo; } //Display the frames per second. UiApplication.getUiApplication().invokeLater(new Runnable() { public void run() { Dialog.alert("Animation time: " + animTime + " ms.\nAvg FPS: " + fps); } }); } //Animation is over. _currentlyAnimating = false; } } public static Bitmap rotateImage(Bitmap oldB, int angle) throws Exception { int w = oldB.getWidth(); int h = oldB.getHeight(); double angRad = (angle % 360)*(Math.PI/180); Bitmap newB = new Bitmap(w,h); int[] oldD = new int[w*h]; int[] newD = new int[w*h]; oldB.getARGB(oldD, 0, w, 0, 0, w, h); int axisX = w/2; int axisY = h/2; for(int x = 0; x < oldD.length; x++) { int oldX = x%w; int oldY = x/w; int op = oldX-axisX; int adj = oldY-axisY; double oldT = MathUtilities.atan2(op, adj); double rad = Math.sqrt((op*op)+(adj*adj)); double newT = oldT+angRad; int newX = (int)MathUtilities.round((rad*Math.sin(newT))+(double)axisX); int newY = (int)MathUtilities.round((rad*Math.cos(newT))+(double)axisY); if(newX<0||newY<0||newX>=w||newY>=h) { newD[x] = 0x00000000; } else { newD[x] = oldD[(newY*w)+newX]; } } newB.setARGB(newD, 0, w, 0, 0, w, h); return newB; } //Let's paint! protected void paint(Graphics graphics) { //Get the screen resolution. int width = Graphics.getScreenWidth(); int height = Graphics.getScreenHeight(); //Counters for the for loops. int count, count2; //Variables to hold temporary x and y values. //Storing these in a defined variable is more efficent //then calculating them inline as the inline calculation //will create a temporary int variable for each calculation. //This would result in the creation of a lot of garbage. int tempX, tempY; if (_drawRunner) { try{ rotateImage(brick, 59); }catch (Exception ex) { ex.printStackTrace(); } graphics.drawBitmap(width-30, height-60, 20, 10, brick, 0, 0); } //end if (_drawRunner) } //end paint //Invoked when the trackwheel is clicked. public boolean trackwheelClick(int status, int time) { boolean retVal = false; //Only start the animation if one is not in progress. if (!_currentlyAnimating) { _currentlyAnimating = true; initialize(); AnimationThread animationThread = new AnimationThread(); animationThread.start(); retVal = true; } return retVal; } //Invoked when the trackwheel is released. public boolean trackwheelUnclick(int status, int time) { return false; } //Invoked when the trackwheel is rolled. public boolean trackwheelRoll(int amount, int status, int time) { return false; } //Invoked when a key is pressed. public boolean keyChar(char key, int status, int time) { boolean retVal = false; int tempY = Graphics.getScreenHeight() - 50; switch (key) { case Characters.ESCAPE: System.exit(0); retVal = true; break; case Characters.ENTER: case Characters.SPACE: //Only start the animation if one is not in progress. if (!_currentlyAnimating) { _currentlyAnimating = true; initialize(); AnimationThread animationThread = new AnimationThread(); animationThread.start(); retVal = true; } break; default: break; } return retVal; } //Implementation of KeyListener.keyStatus. public boolean keyStatus(int keycode, int time) { return false; } //Implementation of KeyListener.keyDown. public boolean keyDown(int keycode, int time) { return false; } //Implementation of KeyListener.keyRepeat. public boolean keyRepeat(int keycode, int time) { return false; } //Implementation of KeyListener.keyUp. public boolean keyUp(int keycode, int time) { return false; } }
Code:package com.msohm.animationDemo; import net.rim.device.api.ui.*; import net.rim.device.api.ui.component.*; import net.rim.device.api.ui.container.*; import net.rim.device.api.system.*; import net.rim.device.api.util.*; import java.util.*; public class AnimationDemo extends UiApplication { //The application enters the event thread by invoking the enterEventDispatcher method. public static void main(String[] args) { AnimationDemo theApp = new AnimationDemo(); theApp.enterEventDispatcher(); } public AnimationDemo() { AnimationScreen animScreen = new AnimationScreen(); pushScreen(animScreen); } }
Code:public static Bitmap rotateImage(Bitmap oldB, int angle) throws Exception { int w = oldB.getWidth(); int h = oldB.getHeight(); double angRad = (angle % 360)*(Math.PI/180); Bitmap newB = new Bitmap(w,h); int[] oldD = new int[w*h]; int[] newD = new int[w*h]; oldB.getARGB(oldD, 0, w, 0, 0, w, h); int axisX = w/2; int axisY = h/2; for(int x = 0; x < oldD.length; x++) { int oldX = x%w; int oldY = x/w; int op = oldX-axisX; int adj = oldY-axisY; double oldT = MathUtilities.atan2(op, adj); double rad = Math.sqrt((op*op)+(adj*adj)); double newT = oldT+angRad; int newX = (int)MathUtilities.round((rad*Math.sin(newT))+(double)axisX); int newY = (int)MathUtilities.round((rad*Math.cos(newT))+(double)axisY); if(newX<0||newY<0||newX>=w||newY>=h) { newD[x] = 0x00000000; } else { newD[x] = oldD[(newY*w)+newX]; } } newB.setARGB(newD, 0, w, 0, 0, w, h); return newB; }
Code:try{ rotateImage(brick, 59); }catch (Exception ex) { ex.printStackTrace(); } graphics.drawBitmap(width-30, height-60, 20, 10, brick, 0, 0);
Thanks.11-07-10 06:38 AMLike 0 - I didn't look at your code, but you can rotate an image using an SVGElement
I used something like this to rotate a gps map
private SVGImage _image;
private SVGMatrix imageTransform;
Document document = _image.getDocument();
_indicatorElement = (SVGElement)document.createElementNS(SVG_NAMESPACE _URI, "image");
imageTransform = _indicatorElement.getMatrixTrait("transform");
imageTransform.mRotate((float)(-currentHeading));
_indicatorElement.setMatrixTrait("transform",image Transform);
edit: (there should not be a space between imageTransform, it's not showing in the post preview)Last edited by Chaoss; 11-08-10 at 09:37 PM.
11-08-10 09:33 PMLike 0 - Thanks for your reply guys.
@LSphone:
When I run it on the BB-Simulator, it shows the original image (does not rotate).
@Chaoss:
Do I have to specify the location here: private SVGImage _image; And where do I specify the rotation angle in your code?11-10-10 11:30 AMLike 0 -
- sample program to spin a png image, example uses a 120px square png image
package spin;
import net.rim.device.api.ui.*;
import net.rim.device.api.system.Display;
import net.rim.device.api.ui.container.*;
import java.lang.Runnable;
import javax.microedition.m2g.*;
import org.w3c.dom.*;
import org.w3c.dom.svg.*;
final class spin extends UiApplication {
spin() {
Screen screen = new Screen();
pushScreen(screen);
}
public static void main(String[] args) throws Exception {
spin app = new spin();
app.enterEventDispatcher();
}
}
class Screen extends MainScreen {
private SVGImage _image;
private ScalableGraphics sg;
private SVGElement svgElement, _brickElement;
private SVGMatrix transform, imageTransform;
private double angle;
private UiApplication UiApp;
private static final String SVG_NAMESPACE_URI = "http://www.w3.org/2000/svg";
private static final String XLINK_NAMESPACE_URI = "http://www.w3.org/1999/xlink";
Screen() {
UiApp = spin.getUiApplication();
int _screenWidth = Display.getWidth();
int _screenHeight = Display.getHeight();
_image = SVGImage.createEmptyImage(null);
Document document = _image.getDocument();
svgElement = (SVGSVGElement)document.getDocumentElement();
svgElement.setFloatTrait("width", _screenWidth);
svgElement.setFloatTrait("height", _screenHeight);
sg = ScalableGraphics.createInstance();
sg.setRenderingQuality(sg.RENDERING_QUALITY_HIGH);
_image.setViewportWidth(_screenWidth);
_image.setViewportHeight(_screenHeight - 64); //room for tab bar
_brickElement = (SVGElement)document.createElementNS(SVG_NAMESPACE _URI, "image");
_brickElement.setId("brickElement");
_brickElement.setTraitNS(XLINK_NAMESPACE_URI, "href", "brick.png");
_brickElement.setFloatTrait("x", -60); //set center of element...
_brickElement.setFloatTrait("y", -60); // to half image size
_brickElement.setFloatTrait("width", 120); //set element size = image size
_brickElement.setFloatTrait("height", 120);
transform = svgElement.getMatrixTrait("transform");
transform.mTranslate(80,80); //set position of element on screen
_brickElement.setMatrixTrait("transform",transform );
svgElement.appendChild(_brickElement);
angle = 1; // degrees to rotate
//rotate element every second
Runnable spinBrick = new Runnable() {
public void run() {
imageTransform = _brickElement.getMatrixTrait("transform");
imageTransform.mRotate((float)(angle));
_brickElement.setMatrixTrait("transform",imageTran sform);
invalidate();
}};
UiApp.invokeLater(spinBrick, 1, true);
}
protected void paint( Graphics graphics ) {
graphics.setBackgroundColor(Color.BLACK);
graphics.clear();
subpaint( graphics );
sg.bindTarget(graphics);
sg.render(100, 100, _image);
sg.releaseTarget();
}
}
edit: sorry bout the formatting, I'm new to the intertubesLast edited by Chaoss; 11-11-10 at 09:07 PM.
11-11-10 09:03 PMLike 0 -
- Forum
- BlackBerry Developers
- Developers Lounge
tiny programm to rotate bitmap (help needed)
LINK TO POST COPIED TO CLIPBOARD