Windows Phone 8.1 camera orientation

Update: The code was missing global bool variable to check if we’re using the front camera, added to code
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!

About Jani Nevalainen

Windows developer who's been working on Microsoft Platforms since 1996. Windows Phone dev MVP 2013, Windows Development Platform MVP 2014. Currently working as Technical Evangelist for Microsoft Finland Developer Experience team.
This entry was posted in Universal Apps, Windows Phone 8.1 and tagged , , . Bookmark the permalink.

15 Responses to Windows Phone 8.1 camera orientation

  1. Farooq says:

    Hi, What is ‘cam’ ?

  2. Dalpat Prajapati says:

    What is “cam” in code?
    mediaCapture.SetPreviewRotation(cam
    ? VideoRotationLookup(sender.CurrentOrientation, true)
    : VideoRotationLookup(sender.CurrentOrientation, false));

  3. David Underhill says:

    I have been working on a camera capture portable library that our company can share between products. We have both Win Store and Phone apps and most of our products revolve media capture and editing. Your post has helped me tremendously and I really appreciate it. I love the Win store/phone platform but it is difficult to find good examples and help when something does not work the way you expected.

    Thanks,
    David.

  4. Alex says:

    Hi Jani,

    I am having a little difficulty in reversing what you’ve done for the purposes of utilizing the rear camera on the Windows Phone instead. Can you help me understand what changes I would need to make? I think I am over simplifying the changes.

    Thank you,
    Alex

    • Alex says:

      Just realized that I wasn’t clear… I DO have the rear cam working, but the recording is still tilted 90 Degrees. I had to set the default of the rear cam to 90 Degrees as is, so I don’t know how to make the change in just the recording setting. For my purposes, I am keeping the phone in Portrait mode, so I will not have to worry about Landscape or rotating the phone.

      Any help or suggestions you have would be awesome. Thank you in advance!

      • Emmanuel says:

        I have exactly the same problem, even if I hardcode the SetRecordRotation to 90 degrees it still saves it flipped 270.

      • Hi Alex, did you look devInfo.Name for back, and then set frontCam to false? Did you do something else?

        • Emmanuel says:

          For my case I did looked for the “back” string in the devInfo.Name, I then changed the flow direction:
          this.capturePreview.FlowDirection = backCam ? FlowDirection.LeftToRight : FlowDirection.RightToLeft;
          And finally I flipped the flags in the DisplayInfo_OrientationChanged method:
          private void DisplayInfo_OrientationChanged(DisplayInformation sender, object args)
          {
          if (takePhotoManager != null)
          {
          takePhotoManager.SetPreviewRotation(backCam ? VideoRotationLookup(sender.CurrentOrientation, false)
          : VideoRotationLookup(sender.CurrentOrientation, true));
          var rotation = VideoRotationLookup(sender.CurrentOrientation, false);
          takePhotoManager.SetRecordRotation(rotation);
          }
          }

          The landscape picture is saved fine but the portrait one is tilted -90 degrees even though in the preview I see it just fine.

  5. Jan Skála says:

    Thank you for this great example! It really saved me tons of hours of work. I spared a lot of time finding a good code example, but none of them is as good as yours. I am only using the back camera, but still I had problems with rotation and stuff. Now I only need to figue out how to stretch the capture element horizontaly, but that s the roblem of my design. So anyway thank you for this.

  6. Gene says:

    Well done. Good information, hard to find.

Leave a Reply

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