Windows Phone 8.1 camera orientation

Using the cameras of Windows Phone 8.1 live viewfinder in Universal apps can be a bit of a challenge. The behavior is different with front and main cameras and most likely you end up with upside down image on your preview, if you run the same code which works for Windows 8.1 when using the front camera. The design of the camera driver is based on WP8.1 chassis specs, and camera orientation is dependent on the native landscape orientation of the display.

Issue here is that the rotation of the front camera and display happens in opposite direction, resulting to inverted image. This all can be a bit confusing, so let’s give you a code which runs on WP8.1 correctly. Note that you need to ifdef this code in Windows for the rotations, or your front camera on tablet will be incorrectly rotated.

First we define the capture element to the XAML like this:

<CaptureElement x:Name="captureElement" 
HorizontalAlignment="Center" 
VerticalAlignment="Center" 
Stretch="UniformToFill">
</CaptureElement>

In the following code we check if front camera is available, and take it in use, otherwise fall back to the main camera. After that we set the camera mirroring according to the chosen camera, as it differs with front and main camera as well. Lastly we subscribe to the orientation change event:

bool frontCam;

...

protected override async void OnNavigatedTo(NavigationEventArgs e)
{
    mediaCapture = new MediaCapture();
    DeviceInformationCollection devices = 
await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);

    // Use the front camera if found one
    if (devices == null) return;
    DeviceInformation info = devices[0];

    foreach (var devInfo in devices)
    {
        if (devInfo.Name.ToLowerInvariant().Contains("front"))
        {
            info = devInfo;
            frontCam = true;
            continue;
        }
    }

    await mediaCapture.InitializeAsync(
        new MediaCaptureInitializationSettings
        {
            VideoDeviceId = info.Id
        });
            
    CaptureElement.Source = mediaCapture;
    CaptureElement.FlowDirection = frontCam ? 
FlowDirection.RightToLeft : FlowDirection.LeftToRight;
    await mediaCapture.StartPreviewAsync();

    DisplayInformation displayInfo = DisplayInformation.GetForCurrentView();
    displayInfo.OrientationChanged += DisplayInfo_OrientationChanged;

    DisplayInfo_OrientationChanged(displayInfo, null);
}

Now we need to adjust the orientation of the capture element according to the screen orientation (the animation makes your eyes bleed, but there’s no way to disable orientation animations for a control). This code is modified from the MSDN Windows 8.1 advanced camera sample.

private void DisplayInfo_OrientationChanged(DisplayInformation sender, object args)
{
if (mediaCapture != null)
{
mediaCapture.SetPreviewRotation(frontCam
? VideoRotationLookup(sender.CurrentOrientation, true)
: VideoRotationLookup(sender.CurrentOrientation, false));
var rotation = VideoRotationLookup(sender.CurrentOrientation, false);
mediaCapture.SetRecordRotation(rotation);
}
}

For the last piece we need to check the video rotation according to the chosen camera like this:

private VideoRotation VideoRotationLookup(DisplayOrientations displayOrientation, bool counterclockwise)
{
switch (displayOrientation)
{
case DisplayOrientations.Landscape:
return VideoRotation.None;

case DisplayOrientations.Portrait:
return (counterclockwise) ? VideoRotation.Clockwise270Degrees : VideoRotation.Clockwise90Degrees;

case DisplayOrientations.LandscapeFlipped:
return VideoRotation.Clockwise180Degrees;

case DisplayOrientations.PortraitFlipped:
return (counterclockwise) ? VideoRotation.Clockwise90Degrees :
VideoRotation.Clockwise270Degrees;

default:
return VideoRotation.None;
}
}

That’s all it requires, have fun with it!

This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *