信息
您所需的主题如下所示。但此主题未包含在此库中。

如何在 Windows Phone 8 的应用中使用相机对焦

2014/6/18

适用于:Windows Phone 8 和 Windows Phone Silverlight 8.1 | Windows Phone OS 7.1

从 Windows Phone OS 7.1 开始,您可以使用 Microsoft.Devices.PhotoCamera 类以编程方式访问手机相机。本主题介绍如何在 Windows Phone 应用中采用编程方式启动自动对焦以及启用触摸对焦功能。本主题是如何为 Windows Phone 8 创建基本相机应用的继续,并且假定您已在该主题中创建了基本相机项目。

提示提示:

从 Windows Phone 8 开始,应用可以将 PhotoCaptureDevice 类用于高级捕获方案。PhotoCaptureDevice 允许应用控制照片属性,例如 ISO、曝光补偿和手动对焦位置(在手机上可用时)。本主题没有演示 PhotoCaptureDevice;有关此类的更多信息,请参见 Windows Phone 8 的高级照片拍摄

本主题与基本相机示例相对应。

本主题包括以下部分。

在本节中,向 UI 中添加一个按钮并在代码隐藏文件中添加所需的逻辑,以在点按 AF 按钮时启动自动对焦。在 OnNavigatedTo 方法中添加 AF 按钮的事件处理程序,在 OnNavigatingFrom 方法中将其删除。并非所有手机都支持自动对焦,因此使用 IsFocusSupported 属性检查此 API 是否可用。正在进行拍摄时尝试对焦将引发异常;将 try/catch 语法与 Focus() 方法的调用结合使用。

启动自动对焦

  1. 打开在如何为 Windows Phone 8 创建基本相机应用中创建的基本相机项目。

  2. 在主页 XAML 文件 MainPage.xaml 中,在 StackPanel 元素中添加以下代码,放在名为 ShutterButtonButton 元素后面。该代码为相机对焦的按钮。

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

    单击该按钮时,会调用之后将在本主题中创建的 focus_Clicked 方法。

    说明注意:

    本练习中的软件自动对焦按钮只是为了演示采用编程方式访问 PhotoCamera API。 若要优化应用用户的体验,我们建议您的应用使用相机上的硬件快门按钮实现该功能。有关如何实现硬件快门按钮的信息,请参见如何访问 Windows Phone 8 中的硬件相机快门按钮

  3. 在主页的代码隐藏文件 MainPage.xaml.cs 中,向 OnNavigatedTo(NavigationEventArgs) 方法添加以下代码。该代码实现 AutoFocusCompleted 事件处理程序。

      
    // The event is fired when autofocus is complete.
    cam.AutoFocusCompleted += new EventHandler<CameraOperationCompletedEventArgs>(cam_AutoFocusCompleted);
    
    
  4. MainPage.xaml.cs 中,向 OnNavigatedTo 方法添加以下代码,放在 Disable UI 注释后面。

    AFButton.IsEnabled = false;
    

    该代码禁用自动对焦按钮。当手机上的相机不可用时使用。

  5. MainPage.xaml.cs 中,调用 Dispose 方法之后,向 OnNavigatingFrom(NavigatingCancelEventArgs) 方法添加以下代码。该代码帮助释放与相机有关的内存。

    cam.AutoFocusCompleted -= cam_AutoFocusCompleted;
    
    
  6. MainPage.xaml.cs 中,向 MainPage 类添加以下代码。该代码通过启动相机对焦操作实现 focus_Clicked 事件的事件处理程序。

        // 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. MainPage.xaml.cs 中,向 MainPage 类添加以下代码。该代码实现 AutoFocusCompleted 事件处理程序以向名为 txtDebugTextBlock 写入一条消息。之所以需要 BeginInvoke 方法,是因为应用的 UI 在另一个线程上运行。

    说明注意:

    对焦操作完成之后,发生 AutoFocusCompleted 事件。Focus()FocusAtPoint(Double, Double) 这两种方法都启动对焦操作。

        void cam_AutoFocusCompleted(object sender, CameraOperationCompletedEventArgs e)
        {
            Deployment.Current.Dispatcher.BeginInvoke(delegate()
            {
                // Write message to UI.
                txtDebug.Text = "Autofocus has completed.";
    
            });
        }
    
    
  8. 在手机上,通过选择“调试 | 启动调试”菜单命令来运行应用。

在这一部分中,向 UI 中添加一些方括号(用于显示点按取景器的位置)并在代码隐藏文件中添加所需的逻辑,以在点按取景器的位置启动对焦。FocusAtPoint(Double, Double) 方法用于实现触摸对焦。

OnNavigatedTo 方法中添加画布点按的事件处理程序。并非所有手机都支持点对焦,因此使用 IsFocusAtPointSupported 属性检查此 API 是否可用。正在进行拍摄时尝试对焦将引发异常;将 try/catch 语法与 FocusAtPoint(Double, Double) 方法的调用结合使用。

说明注意:

本部分假定您已经完成上一部分启动自动对焦

实现触摸对焦的步骤

  1. 在主页 XAML 文件 MainPage.xaml 中,在 Canvas 控件中添加以下代码,放置在包含名为 viewfinderBrush 的视频画笔的 Canvas.Background 元素下面。

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

    该代码是一个 TextBlock 元素,该元素包含用于指示发生对焦位置的方括号。仅当相机对焦时才显示方括号。

  2. 在主页的代码隐藏文件 MainPage.xaml.cs 中,向 OnNavigatedTo(NavigationEventArgs) 方法添加以下代码。

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

    该代码处理画布点按的事件处理程序。当用户点按取景器以启动触摸对焦时,调用 focus_Tapped 方法。

  3. MainPage.xaml.cs 中,向 MainPage 类添加以下代码。

            // 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().";
                        });
                    }
                }
            }
    
    

    该代码通过放置焦点方括号(使用估计的坐标)、确定焦点、显示焦点方括号以及在与点按位置对应的点上启动对焦来启用触摸对焦。

    方括号的 X 和 Y 位置与 TextBlock 控件的左上角相对应。放置方括号时,从坐标中减去一些量以便更好地将方括号放在点按位置附近。

    FocusAtPoint(Double, Double) 方法参数基于图像的百分比。为了简化该代码,有意将相机取景器图像显示在将触发点按事件的同一控件上,即名为 viewfinderCanvasCanvas 控件上。对于该方法,传递给 focus_Tapped 方法的 GestureEventArgs 中的坐标直接相对于 Canvas 控件宽度和高度。

  4. MainPage.xaml.cs 中,向 cam_AutoFocusCompleted 方法添加以下代码,放在 BeginInvoke 调用内,位于 txtDebug 语句之后。

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

    该代码在完成对焦操作之后隐藏对焦方括号。

显示: