Rotating a Bitmap in Mono for Android and MonoTouch

In a post last year, I wrote about a need I had to display a bitmap received from a web service but rotated by 90 degrees. This was for an Android application I was writing at the time using Eclipse and Java. As I recently stated, I’ve been looking at using C# to build iOS apps and decided to go the whole hog and checkout Mono for Android too. So I began by porting that application to Mono for Android which took around a week. Now I’ve nearly finished porting it to MonoTouch, the iOS equivalent. I can’t express how much I love the ability to use C# to write for these two platforms. Everyone associated with all things Mono should be congratulated for a terrific achievement, especially when you consider that even Microsoft are using Mono to write iOS apps now! Who’d have thunk it? :)

Anyway, for completeness I thought I would show the rotating bitmap code again but this time using C# code for the Android and iOS flavours of Mono. Hope it’s of use to someone out there.

Android:


// assume something hands us a bitmap
Bitmap myBitmap = GetImageFromWebService();

// get the width and height of the current view
Display d = WindowManager.DefaultDisplay;
int x = d.Width;
int y = d.Height;
	              
// scale it to fit the screen
Bitmap scaledBmp = Bitmap.CreateScaledBitmap(myBitmap, y, x, true);
	       
// create a matrix, rotate it anti-clockwise by 90 degrees
Matrix matrix = new Matrix();
matrix.PostRotate(-90);      
	       
// create a new rotated bitmap using the our original bitmap and the matrix measurements
Bitmap rotatedBmp = Bitmap.CreateBitmap(scaledBmp, 0, 0, scaledBmp.Width, scaledBmp.Height, matrix, true);    
	       
return rotatedBmp;

iOS:

	 

// assume something hands us a bitmap
UIImage myImg = GetImageFromWebService();
       
SizeF newSize = new SizeF(myImg.Size.Height, myImg.Size.Width);
	
UIGraphics.BeginImageContext(newSize);
CGContext ctx = UIGraphics.GetCurrentContext();
			
ctx.TranslateCTM(myImg.Size.Height, myImg.Size.Width); 
			
// scale
ctx.ScaleCTM(1f, -1f);
			
// rotate anti-clockwise
ctx.RotateCTM(1.57079633f);
			
// draw a new image with the same size
ctx.DrawImage(new RectangleF(0, 0, myImg.Size.Width, myImg.Size.Height), myImg.CGImage);
UIImage rotatedImage = UIGraphics.GetImageFromCurrentImageContext();
	
UIGraphics.EndImageContext();
		
return rotatedImage;

To be fair, the Android version is not that different from before (as you’d expect really) what with Java and C# being of similar syntax. The iOS version however is quite a bit different and perhaps a little bit more involved but it’s still fairly easy. You can experiment with the values passed to the various CTM (current transformation matrix) methods or change the size of the newly drawn image in the DrawImage method to see how they affect the resulting image display.

As for why I rewrote the Java based app in Mono C# well, for one C# is IMHO a nicer language than Java, and two, I extracted the business logic out into a separate assembly which is now shared between both the Android and iOS applications which means I only have to add new features or fix bugs in one place. It’s also been a lot easier and quicker to create the iOS version of the app than I’m sure it would have been if I had gone down the Objective-C route.

Advertisements
Rotating a Bitmap in Mono for Android and MonoTouch

Rotating a Bitmap in Android

I’m learning a lot from my first experience with Android development, and find the SDK and APIs pretty easy to work with. I’ve found you can achieve some pretty impressive results with relatively few lines of code but sometimes I end up thinking a problem is harder than it actually turns out to be. Rotating bitmaps is one of them.

I have a need in my android app to pull an image from a web service, rotate it 90 degress, scale it and then display it in the centre of the screen. This is what I did to achive that goal.


// Get the image we want to work with from a URL
Bitmap myBitmap = BitmapFactory.decodeStream(downloadImageFromWeb());

// or just load a resource from the res/drawable directory:
Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.android1);

// find the width and height of the screen:
Display d = getWindowManager().getDefaultDisplay();
int x = d.getWidth();
int y = d.getHeight();

// get a reference to the ImageView component that will display the image:
ImageView img1 = (ImageView)findViewById(R.id.img1);

// scale it to fit the screen, x and y swapped because my image is wider than it is tall
Bitmap scaledBitmap = Bitmap.createScaledBitmap(myBitmap, y, x, true);

// create a matrix object
Matrix matrix = new Matrix();
matrix.postRotate(-90); // anti-clockwise by 90 degrees

// create a new bitmap from the original using the matrix to transform the result
Bitmap rotatedBitmap = Bitmap.createBitmap(scaledBitmap , 0, 0, scaledBitmap .getWidth(), scaledBitmap .getHeight(), matrix, true);

// display the rotated bitmap
img1.setImageBitmap(rotatedBitmap);

The key to the rotation is the Matrix object. According to the Android documentation “The Matrix class holds a 3×3 matrix for transforming coordinates”. And er, that’s it. The actual rotation is applied using the createBitmap overload that takes the bitmap to transform and the matrix instance that has had the postRotate method called on it. Buried in the middle is a call to scale the bitmap but that’s not the focus here.

Having written the code, you of course need an ImageView defined in your layout xml file which we can call setImageBitmap on as shown above. This is the layout I used.


<ImageView
android:background="#ffffffff"
android:id="@+id/img1"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:maxWidth="250dip"
android:maxHeight="250dip"
android:adjustViewBounds="true"
/>

Note that the maxWidth and maxHeight properties ensure that I don’t scale the image up too much (I’m still experimenting as to what looks good across different screen sizes) though they don’t seem to have any effect unless you  include the adjustViewBounds=”true” attribute as well.

So, in the end, rotating a bitmap is trivial and nowhere near as complex as I originally assumed it might be – a pattern I’m starting to see repeated throughout my Android development experience.

Rotating a Bitmap in Android