Windows Phone 7: Working with Camera Tasks

We’re pleased to have another great post from our friends at Manning to share with you based on their soon to be release book, “Windows Phone 7 in Action”.Windows Phone 7 in Action

As you may know, Mindscape offers one of the best suites of Windows Phone 7 controls including some amazing charts. We’d love to see you build applications with what you learn in this article. To make it even easier we’ve got a fantastic offer for our readers – get 40% off Windows Phone 7 in Action with the following discount code:


This article is based on Windows Phone 7 in Action. It is being reproduced here by permission from Manning Publications . Manning early access books and ebooks are sold exclusively through Manning. Visit the book’s page for more information.

Working with Camera Tasks

All Windows Phones have at least one built-in camera. Microsoft’s minimum hardware specification requires a camera with a flash. Some phones have a second front-facing camera. The Windows Phone class library contains two chooser tasks that provide limited access to the camera, or more specifically, to pictures taken by the camera or pictures that exist in the media library.

Note: Only photographs are accessible via the chooser tasks. The chooser classes do not allow you to access videos from the camera.

The chooser tasks are the PhotoChooserTask and CameraCaptureTask. Let’s look at choosing from the media library with the PhotoChooserTask first.

Choosing a photo with PhotoChooserTask

All phone users are familiar with how to take a picture with their mobile device since taking picture is a part of their daily phone usage. But, as programmers, knowing how to take a photo with the phone is not enough. The PhotoChooserTask allows an application to launch the built-in Photo Chooser application.

You need to know how to use the camera from your code and how to integrate the camera with your custom application. This is what you’re going to learn in this article.

PhotoChooserTask allows users to select the photo from phone memory with the built-in Photo Chooser. The Photo Chooser has a navigation button that can take you to the camera application. The PhotoChooserTask is handy for those applications that allow a user to choose a photograph and use it somewhere in the application. One example is adding a picture to a user’s profile.

If you are coming from a .NET background then you might be wondering about the differences between OpenFileDialog and PhotoChooserTask when they both select files. The Windows Phone APIs do not give you a generic file picker so you will have to use PhotoChooserTask in order to allow the user to select a photo in your application. Table 1 describes the members of PhotoChooserTask.

PhotoChooserTask Members

Name Type Description
Show Method Shows the Phone Chooser application.
ShowCamera Property Gets or sets whether the user is presented with a button for launching the camera during the photo choosing process
Completed Event Occurs when a chooser task is completed

PhotoChooserTask’s Show method launches the built-in Photo Chooser application. When the Show method executes, your application is moved to the background as the operating system switches to Photo Chooser application. The Photo Chooser application is shown in figure 1. The Photo Chooser opens to a list of albums that the user has created in the phone. There are only two default albums in the emulator, named “Camera Roll” and “Simple Picture,” but the user might have more in a real phone device. Note that “Camera Roll” is the default album that stores all photos taken by the phone camera.

Windows Phone Photo Chooser application with camera button
A screenshot of the built-in Photo Chooser application with camera button

The ShowCamera property can be set to true if the user should see the camera icon in the application bar. When the camera icon is shown, the user has the option to take a new picture. It is always a best practice to set the ShowCamera property to true because the user may want to take a new photo right away instead of selecting one from the photo albums.

Let’s add an ApplicationBar menu item to show the PhotoChooserTask in our PhotoEditor application.

    <shell:ApplicationBar IsVisible=“True” IsMenuEnabled=“True”>
            <shell:ApplicationBarMenuItem Text=“choose photo” 
                Click=“Choose_Click” />

The ApplicationBarMenuItem displays the text “choose photo.” The click event hander for the menu item constructs a PhotoChooserTask and sets the ShowCamera property to true.

private void Choose_Click(object sender, EventArgs e)
    var task = new PhotoChooserTask();
    task.ShowCamera = true;  #1
    task.Completed += chooserTask_Completed;

The Completed event is wired up to the chooserTask_Completed event handler. When the Show method is called, your application is paused and placed in the Task Switcher’s back stack. When the user completes the chooser operation, the operating system navigates back to your application. The Completed event handler is called when the application resumes operation in the foreground.

Note: The media library is locked when a device is connected to a computer and the Zune software is running. When the media library is locked, you will encounter errors when testing the PhotoChooserTask.

The Completed event will be raised when user selects a photo from a photo library, takes a new photo, or uses the back button to navigate back to the application. Listing 1 shows how to handle the Completed event and display the selected photo in the image control.

Displaying the selected photograph

private WriteableBitmap currentImage; #1
void chooserTask_Completed(object sender, PhotoResult e)
    if (e.TaskResult == TaskResult.OK) 
        currentImage = PictureDecoder.DecodeJpeg(e.ChosenPhoto); #2
        photoContainer.Fill = new                     #3
            ImageBrush{ ImageSource = currentImage }; #3
        imageDetails.Text = string.Format(“Image from {0}\n”, 
        imageDetails.Text += string.Format(“Original filename:\n{0}”, 
        photoContainer.Fill = new SolidColorBrush(Colors.Gray);
        imageDetails.Text = e.TaskResult.ToString();

#1 Field to hold the chosen photo
#2 Photo stream is in e.ChosenPhoto
#3 Displays the image with a brush

First, we need a new WriteableBitmap field named currentImage (#1) in which we store the photograph shown in the photoContainer Rectangle control. It is a best practice to check the TaskResult property to determine if the chooser task completed OK or if the task was canceled. The PhotoResult class defines two properties named ChosenPhoto and OriginalFileName. ChosenPhoto contains the selected picture’s data in a Stream. We pass the image stream to the DecodeJpeg method of the helper class named PictureDecoder (#2).

The PictureDecoder class is found in the Microsoft.Phone namespace. The DecodeJpeg method builds a WriteableBitmap. We use the WriteableBitmap as the source for an ImageBrush, and the brush is used as the Fill for the photoContainer (#3). Finally, we build a message informing the user that the picture came from the PhotoChooserTask and had the filename specified in the OriginalFileName property.

When the TaskResult is not OK, we clear the photoContainer by setting the Fill property to a SolidColorBrush and display the TaskResult value in the imageDetails TextBlock.

Run the application, select the choose photo menu item, and pick a photo. The photo you choose should be shown in the application when the PhotoChooserTask completes. Next, we look at how to use the CameraCaptureTask.

Taking photos with CameraCaptureTask

CameraCaptureTask is another useful task that allows developers to launch the built-in camera application. Unlike PhotoChooserTask, it allows you to open the camera directly from an application without requiring the user to perform additional clicks. Shown in figure 2, the camera application in the emulator shows a placeholder white screen with a moving black block. You can take a photo in the emulator by clicking the round widget located at the right top corner. We recommend you to use a physical device to test this task.

Windows Phone Camera Application
Figure 2 The camera application in the emulator

The CameraCaptureTask does not have any properties and only implements the Show method. Let’s show the camera application by calling the Show method from the click event of a new menu item we add to MainPage.xaml.

<shell:ApplicationBarMenuItem Text=“capture photo” Click=“Capture_Click” />

The snippet below shows how to use CameraCaptureTask.

private void Capture_Click(object sender, EventArgs e)
    var task = new CameraCaptureTask();
    task.Completed += chooserTask_Completed;

We subscribe to the Completed event to receive the photo stream from the camera and we call the Show method to launch the camera. For Completed event, we can use the same event handler method that we used in PhotoChooserTask sample.

Deploy the updated application to your phone, run the application and choose the capture photo menu option. Hold the phone in the landscape orientation, snap a picture and press the accept button. When the task completes, you should see your new photo displayed in the photoContainer. Select the capture photo menu option again, but, this time, hold your phone in the portrait orientation when you snap the picture. When the task returns this time, the new picture is displayed sideways. The important thing to note is that the image stream that returns from Camera will not respect the orientation of your application. We show you how to handle the orientation of a picture in the next part.

Handling picture orientation in CameraCaptureTask

Please take a look at figure 3. Do you notice that there is something wrong? The orientation of the photograph does not match the orientation of the application.

Windows Phone orientation problems with CameraCaptureTask
Figure 3 Orientation problems with CameraCaptureTask

The photo stream that returns from the camera does not know or care about the orientation of your application. The picture’s orientation will be based on how the user holds the phone while taking the picture. We cannot ask our user to hold the photo in specific position and they will hold the phone however they like. All we can do is to adjust the orientation of photo before showing it in our application.

Tip: The image rotation techniques shown in this section were inspired by Microsoft blogger Tim Heuer, who wrote very good post about orientation mismatch in his blog. You can read his blog post here.

The CameraCaptureTask writes metadata about the picture to the stream along with the image data. The image data and metadata are in the Exchange Image File Format (EXIF). The EXIF format has an attribute that we can read to determine the orientation of the photo. The PhotoResult’s ChosenPhoto property is a Stream and we need a way to extract the EXIF data from the stream. In our sample, we are going to use ExifLib, an open source EXIF library that can be downloaded here. We have included the ExifLib assembly in the sample project. Feel free to use an EXIF library of your choice or you can even roll your own library.

Before we think about how to modify the orientation, we need to figure out the default orientation of the photo that we get from the camera and how the orientation is different from the application’s orientation. Figure 4 shows the possible combinations of application and camera orientation.

Windows Phone different ways of holding camera, photo outputs and degrees that the picture needs to be rotated.
Figure 4 Different ways of holding camera, photo outputs, and degrees that the picture needs to be rotated

This figure shows four different ways of holding the camera and the output in very clear manner. The first column of this diagram illustrates that our sample application is always in a portrait orientation. The second column shows the different ways of holding the camera. The third column displays the output photo from the camera. As you can see, the default orientation of photo will be different based on the way that the user holds the camera. The last column shows how many degrees we need to rotate the photo in order to get an orientation that matches the application.

The code that performs the desired modifications shown in figure 4 is implemented in two steps. The first step calculates the angle to rotate the image, and the second step performs the rotation. Listing 2 demonstrates how to calculate the degree of rotation in the GetAngleFromExif method.

Calculate how many degrees to rotate a photo

using ExifLib; #A
using System.IO; 
int GetAngleFromExif(Stream imageStream)
    var position = imageStream.Position;
    imageStream.Position = 0;
    ExifOrientation orientation = ExifReader.ReadJpeg(  #1
        imageStream, String.Empty).Orientation;         #1
    imageStream.Position = position;
    switch (orientation) #2
        case ExifOrientation.TopRight:
            return 90;
        case ExifOrientation.BottomRight:
            return 180;
        case ExifOrientation.BottomLeft:
            return 270;
        case ExifOrientation.TopLeft:
        case ExifOrientation.Undefined:
            return 0;

#A Uses the EXIF library
#1 Reads the orientation
#2 Determines the rotation angle

First, we read the orientation from the EXIF formatted stream. The ExifReader.ReadJpeg method accepts an image stream and returns a JpegInfo instance. The JpegInfo object contains information stored in the EXIF header in the image stream, including its orientation. We extract the orientation, in the form of an ExifOrientation instance, from the Orientation property (#1). Based on that, we will define how many degrees we need to rotate (#2). We suggest that you compare the implementation and the diagram in figure 4 to understand more details.

Once we know how many degrees we need to rotate the original photo, it’s very easy to create a new photo with the correct orientation based on the original photo. The WriteableBitmap class provides direct access to the pixel level information of bitmaps. The image data is accessed through the Pixels property, a one-dimensional array of pixels laid out in a row first pattern. The PixelWidth and PixelHeight properties are used to determine how many rows and columns of pixels exist in a two-dimensional image. The first row of pixels resides in the Pixels array from index 0 to PixelWidth – 1. The second row of images resides in the Pixels array from index PixelWidth to 2 * PixelWidth – 1. Listing 3 shows how to read the pixels from original photo and copy them to the right position in the new bitmap image.

Listing 3 Copy the pixels from original bitmap to new bitmap

private WriteableBitmap RotateBitmap(WriteableBitmap source, 
    int width, int height, int angle)
    var target = new WriteableBitmap(width, height);  #1
    int sourceIndex = 0;
    int targetIndex = 0;
    for (int x = 0; x < source.PixelWidth; x++)
        for (int y = 0; y < source.PixelHeight; y++)
            sourceIndex = x + y * source.PixelWidth;
            switch (angle) #2
                case 90:
                    targetIndex = (source.PixelHeight - y - 1) 
                        + x * target.PixelWidth;
                case 180:  
                    targetIndex = (source.PixelWidth - x - 1) 
                        + (source.PixelHeight - y - 1) * source.PixelWidth;
                case 270:  
                    targetIndex = y + (source.PixelWidth - x - 1) 
                        * target.PixelWidth;
            target.Pixels[targetIndex] = source.Pixels[sourceIndex]; #3
    return target;

#1 Creates an empty bitmap
#2 Determines target location
#3 Copies pixels

The RotateBitmap method accepts four parameters which are the source bitmap, the width and height of the new bitmap and the angle the bitmap should be rotated. The method starts off creating a new WriteableBitmap with the specified width and height (#1). We loop through each pixel in the source bitmap, calculating the index of the source pixel and the index in the target bitmap where we will copy the pixel. Depending on the rotation angle (#2), we calculate the target index using one of three different expressions. Finally, we copy the pixel (#3) from the source bitmap to the target bitmap.

Note: If you would like more information about WriteableBitmap, please read the MSDN documentation for Silverlight’s version of WriteableBitmap.

RotateBitmap accepts a WriteableBitmap. The CameraOperationCompletedEventArgs passed to the camera_CaptureCompleted method provides a Stream. Currently, the camera_CaptureCompleted method uses DecodeJpeg to convert the stream to a WriteableBitmap. Let’s wrap the call to the DecodeJpeg and RotateBitmap methods in a new DecodeImage method. The code for the new method is shown in listing 4.

Listing 4 Decoding the image stream

private WriteableBitmap DecodeImage(Stream imageStream, int angle)
    WriteableBitmap source = PictureDecoder.DecodeJpeg(imageStream); 
        case 90: 
        case 270: 
            return RotateBitmap(source, source.PixelHeight, #1
                source.PixelWidth, angle);                  #1
        case 180: 
            return RotateBitmap(source, source.PixelWidth, 
                source.PixelHeight, angle);
            return source;  #2

#1 Swaps width and height
#2 Skips RotateBitmap

The new DecodeImage class accepts an image stream and the rotation angle. The first step is to convert the image stream into a WriteableBitmap using the PictureDecoder helper class. Next we examine the degree of rotation, calling RotateBitmap if necessary. When we are rotating the image by 90 or 270 degrees, we are swapping the width and height (#1). When the angle is 0, we do not call RotateBitmap (#1).

With the new GetAngleFromExif and DecodeImage methods in place, we can update the chooserTask_Completed method to rotate the captured photos. In the completed event handler, replace the call to PictureDecoder.DecodeJpeg with the following snippet.

int angle = GetAngleFromExif(e.ChosenPhoto);
currentImage = DecodeImage(e.ChosenPhoto, angle);


You now have a good understanding of how PhotoChooserTask and CameraCaptureTask work. You have also learned how to handle the picture orientation. These chooser tasks are useful when choosing a picture is a secondary feature of your application.

Tagged as Phone Elements

Leave a Reply


Join our mailer

You should join our newsletter! Sent monthly:

Back to Top