Jan 14, 2013

Fixing the rotation - Instant Mustache #8

This article is part of a series of articles about the development process of Instant Mustache, a fun camera app that adds mustaches to all faces using face detection. Click here to get a chronological list of all published articles about Instant Mustache.

Wrong orientation

If you run the current version of Instant Mustache and take some pictures you'll notice something odd: The orientation of the taken pictures is sometimes wrong. This may depend on the device you are using. When using a Galaxy Nexus the picture will be rotated 90° to the left when taking a picture in portrait mode but will be rotated correctly when taking a picture in landscape mode.

Wrong orientation of photo that has been taken in portrait mode

How does this happen? You may remember that we've used Camera.setDisplayOrientation() in one of the previous articles to explicitly set the display rotation. First, this setting only affects the preview picture. The picture passed to the Camera.ShutterCallback isn't affected by this setting. And second, we still have to account into how the device is rotated in the moment of taking the picture.

Detecting and remembering the orientation

What we need to do in our code is to register an OrientationEventListener to get notified whenever the orientation changes. We'll remember this orientation and use this to rotate the taken image once the callback returns.

Whenever the orientation changes onOrientationChanged(int) of the listener will be called. The orientation will be passed to the method in degrees, ranging from 0 to 359. We need to normalize this value as we are only interested in 90° steps for rotating the picture.

CameraOrientationListener.normalize()
Another method called rememberOrientation() will be used to save the orientation of the device in the moment of the user pressing the shutter button.

CameraFragment.takePicture()

Rotating the picture

Now we just need to rotate the Bitmap. We do this by creating a new Bitmap object and applying a rotated Matrix to the pixels. The rotation angle is calculated by summing the remembered orientation, the display orientation and the natural rotation of the device.

CameraFragment.onPictureTaken()

Result

Photos rotated correctly in portrait and landscape mode