How to use camera focus in an app for Windows Phone 8

May 10, 2014

Applies to: Windows Phone 8 and Windows Phone Silverlight 8.1 | Windows Phone OS 7.1

Starting with Windows Phone OS 7.1, you can programmatically access the phone’s camera using the Microsoft.Devices.PhotoCamera class. This topic describes how to programmatically initiate autofocus and enable touch-focus functionality in your Windows Phone app. It is a continuation of How to create a base camera app for Windows Phone 8 and assumes you have already created the base camera project in that topic.

TipTip:

Starting with Windows Phone 8, apps can use the PhotoCaptureDevice class for advanced capture scenarios. PhotoCaptureDevice allows apps to control photo properties such as ISO, exposure compensation, and manual focus position (when available on the phone). This topic doesn’t demonstrate PhotoCaptureDevice; for more info about this class, see Advanced photo capture for Windows Phone 8.

This topic corresponds to the Basic Camera Sample.

This topic contains the following sections.

In this section, you add a button to the UI and add the necessary logic in the code-behind file to initiate autofocus when the AF button is tapped. The event handlers for the AF button are added in the OnNavigatedTo method and removed in the OnNavigatingFrom method. Not all phones support autofocus, so the IsFocusSupported property is used to check if the API is available. Attempting to focus while a capture is in progress will cause an exception; use try/catch syntax with calls to the Focus() method.

To initiate autofocus

  1. Open your base camera project created in How to create a base camera app for Windows Phone 8.

  2. In the main page XAML file, MainPage.xaml, add the following code in the StackPanel element, after the Button element named ShutterButton. This code is the button for camera focus.

    <Button Name="AFButton" Content="AF" Click="focus_Clicked" FontSize="26" FontWeight="ExtraBold" Height="75"/>
    
    
    

    When this button is clicked, it calls the focus_Clicked method, a method that is created later in this topic.

    NoteNote:

    The software autofocus button in this exercise is only for demonstrating programmatic access to the PhotoCamera API. To optimize the experience for the app user, we recommend that your app uses the hardware shutter button on the camera for this functionality. For info about how to implement the hardware shutter button, see How to access the hardware camera shutter button in Windows Phone 8.

  3. In the code-behind file for the main page, MainPage.xaml.cs, add the following code to the OnNavigatedTo(NavigationEventArgs) method. This code implements the AutoFocusCompleted event handler.

      
    // The event is fired when autofocus is complete.
    cam.AutoFocusCompleted += new EventHandler<CameraOperationCompletedEventArgs>(cam_AutoFocusCompleted);
    
    
  4. In MainPage.xaml.cs, add the following code to the OnNavigatedTo method, just after the Disable UI comment.

    AFButton.IsEnabled = false;
    

    This code disables the autofocus button. It’s used when a camera isn’t available on the phone.

  5. In MainPage.xaml.cs, add the following code to the OnNavigatingFrom(NavigatingCancelEventArgs) method after calling the Dispose method. This code helps release memory related to the camera.

    cam.AutoFocusCompleted -= cam_AutoFocusCompleted;
    
    
  6. In MainPage.xaml.cs, add the following code to the MainPage class. This code implements the event handler for the focus_Clicked event by initiating the camera focus operation.

        // Provide autofocus in the viewfinder.
        private void focus_Clicked(object sender, System.Windows.RoutedEventArgs e)
        {
            if (cam.IsFocusSupported == true)
            {
                //Focus when a capture is not in progress.
                try
                {
                    cam.Focus();
                }
                catch (Exception focusError)
                {
                    // Cannot focus when a capture is in progress.
                    this.Dispatcher.BeginInvoke(delegate()
                    {
                        txtDebug.Text = focusError.Message;
                    });
                }
            }
            else
            {
                // Write message to UI.
                this.Dispatcher.BeginInvoke(delegate()
                {
                    txtDebug.Text = "Camera does not support programmable autofocus.";
                });
            }
        }
    
    
  7. In MainPage.xaml.cs, add the following code to the MainPage class. This code implements the AutoFocusCompleted event handler to write a message to the TextBlock named txtDebug. The BeginInvoke method is required because the UI of the app runs on a different thread.

    NoteNote:

    The AutoFocusCompleted event occurs after the focus operation is completed. Both methods, Focus() and FocusAtPoint(Double, Double), initiate the focus operation.

        void cam_AutoFocusCompleted(object sender, CameraOperationCompletedEventArgs e)
        {
            Deployment.Current.Dispatcher.BeginInvoke(delegate()
            {
                // Write message to UI.
                txtDebug.Text = "Autofocus has completed.";
    
            });
        }
    
    
  8. On a phone, run the app by selecting the Debug | Start Debugging menu command.

In this section, you add some brackets to the UI (to show where the viewfinder was tapped) and add the necessary logic in the code-behind file to initiate a focus at the point where the viewfinder was tapped. The FocusAtPoint(Double, Double) method is used to implement touch focus.

The event handlers for the canvas tap are added in the OnNavigatedTo method. Not all phones support focus at point, so the IsFocusAtPointSupported property is used to check if the API is available. Attempting to focus while a capture is in progress will cause an exception; use try/catch syntax with calls to the FocusAtPoint(Double, Double) method.

NoteNote:

This section assumes you have already completed the previous section, Initiating Autofocus.

To implement touch focus

  1. In the main page XAML file, MainPage.xaml, add the following code within the Canvas control, below the Canvas.Background element that contains the video brush named viewfinderBrush.

                <!-- Brackets for Touch Focus -->
                <TextBlock 
                    x:Name="focusBrackets" 
                    Text="[   ]" 
                    FontSize="40"
                    Visibility="Collapsed"/>
    
    

    This code is a TextBlock element that contains brackets that are used to indicate where a focus is occurring. The brackets are only shown when the camera is focusing.

  2. In the code-behind file for the main page, MainPage.xaml.cs, add the following code to the OnNavigatedTo(NavigationEventArgs) method.

        // The event is fired when the viewfinder is tapped (for focus).
        viewfinderCanvas.Tap += new EventHandler<GestureEventArgs>(focus_Tapped);
    
    

    This code handles the event handler for the canvas tap. When the user taps on the viewfinder to initiate touch focus, the focus_Tapped method is called.

  3. On MainPage.xaml.cs, add the following code to the MainPage class.

            // Provide touch focus in the viewfinder.
            void focus_Tapped(object sender, GestureEventArgs e)
            {
                if (cam != null)
                {
                    if (cam.IsFocusAtPointSupported == true)
                    {
                        try
                        {
                            // Determine the location of the tap.
                            Point tapLocation = e.GetPosition(viewfinderCanvas);
    
                            // Position the focus brackets with the estimated offsets.
                            focusBrackets.SetValue(Canvas.LeftProperty, tapLocation.X - 30);
                            focusBrackets.SetValue(Canvas.TopProperty, tapLocation.Y - 28);
    
                            // Determine the focus point.
                            double focusXPercentage = tapLocation.X / viewfinderCanvas.Width;
                            double focusYPercentage = tapLocation.Y / viewfinderCanvas.Height;
    
                            // Show the focus brackets and focus at point.
                            focusBrackets.Visibility = Visibility.Visible;
                            cam.FocusAtPoint(focusXPercentage, focusYPercentage);
    
                            // Write a message to the UI.
                            this.Dispatcher.BeginInvoke(delegate()
                            {
                                txtDebug.Text = String.Format("Camera focusing at point: {0:N2} , {1:N2}", focusXPercentage, focusYPercentage);
                            });
                        }
                        catch (Exception focusError)
                        {
                            // Cannot focus when a capture is in progress.
                            this.Dispatcher.BeginInvoke(delegate()
                            {
                                // Write a message to the UI.
                                txtDebug.Text = focusError.Message;
                                // Hide focus brackets.
                                focusBrackets.Visibility = Visibility.Collapsed;
                            });
                        }
                    }
                    else
                    {
                        // Write a message to the UI.
                        this.Dispatcher.BeginInvoke(delegate()
                        {
                            txtDebug.Text = "Camera does not support FocusAtPoint().";
                        });
                    }
                }
            }
    
    

    This code enables touch focus by positioning the focus brackets (using estimated coordinates), determining the focus points, showing the focus brackets, and initiating focus at a point corresponding to the tap location.

    The X and Y position of the brackets correspond to the top-left of the TextBlock control. When positioning the brackets, some amount is subtracted from the coordinates to better position the brackets “around” the tap location.

    The FocusAtPoint(Double, Double) method parameters are based on a percentage of the image. To simplify this code, the camera viewfinder image was deliberately displayed on the same control that would trigger the tap event, the Canvas control named viewfinderCanvas. With this approach, the coordinates from the GestureEventArgs passed to the focus_Tapped method are directly relative to the Canvas control width and height.

  4. In MainPage.xaml.cs, add the following code to the cam_AutoFocusCompleted method, within the BeginInvoke call and just after the txtDebug statement.

        // Hide the focus brackets.
        focusBrackets.Visibility = Visibility.Collapsed;
    
    

    This code hides the focus brackets after the focus operation has completed.

Show:
© 2014 Microsoft