與眾不同 windows phone (21) - Device(設備)之攝像頭(拍攝照片, 錄制視頻)


[索引頁]
[源碼下載]


與眾不同 windows phone (21) - Device(設備)之攝像頭(拍攝照片, 錄制視頻)



作者:webabcd


介紹
與眾不同 windows phone 7.5 (sdk 7.1) 之設備

  • 用攝像頭拍攝照片
  • 用攝像頭錄制視頻



示例
1、演示如何使用攝像頭拍攝照片
ImageDemo.xaml

<phone:PhoneApplicationPage 
    x:Class="Demo.Device.Camera.ImageDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Landscape" Orientation="Landscape"
    mc:Ignorable="d" d:DesignHeight="480" d:DesignWidth="800"
    shell:SystemTray.IsVisible="False">

    <Grid x:Name="LayoutRoot" Background="Transparent">
        <StackPanel Orientation="Vertical">

            <StackPanel Orientation="Horizontal">
                <Canvas Width="320" Height="240">
                    <Canvas.Background>
                        <VideoBrush x:Name="videoBrush" />
                    </Canvas.Background>
                </Canvas>

                <!--顯示拍攝到的圖片-->
                <Image Name="imgCapture" Width="320" Height="240" Margin="20 0 0 0" />
                <!--顯示拍攝到的圖片的縮略圖-->
                <Image Name="imgCaptureThumbnail" Width="32" Height="24" Margin="20 0 0 0" />
            </StackPanel>

            <StackPanel Orientation="Horizontal">
                <Button x:Name="btnShutter" Content="快門" Click="btnShutter_Click" />
                <Button x:Name="btnFlash" Content="閃光燈" Click="btnFlash_Click" />
                <Button x:Name="btnResolution" Content="分辨率" Click="btnResolution_Click" />
            </StackPanel>

            <TextBlock Name="lblMsg" />

        </StackPanel>
    </Grid>

</phone:PhoneApplicationPage>

ImageDemo.xaml.cs

/*
 * 演示如何使用攝像頭拍攝照片
 * 
 * PhotoCamera - 用於提供相機功能
 *     CameraType - 攝像頭的類型(Microsoft.Devices.CameraType 枚舉)
 *         Primary - 主攝像頭
 *         FrontFacing - 前置攝像頭
 *     AvailableResolutions - 獲取攝像頭的可用分辨率集合(返回一個 IEnumerable<Size> 類型的對象)
 *     FlashMode - 相機的閃光燈模式(Microsoft.Devices.FlashMode 枚舉)
 *         On - 啟用閃光燈
 *         Off - 禁用閃光燈
 *         Auto - 自動閃光燈
 *         RedEyeReduction - 消除紅眼閃光燈
 *     Resolution - 相機的分辨率
 *     Orientation - 取景器與相機傳感器對齊所需要順時針旋轉的度數(只讀)
 *     
 *     CaptureImage() - 拍攝相機當前捕獲到的照片
 *     IsFlashModeSupported(FlashMode mode) - 相機是否支持指定的閃光燈模式
 *     
 *     Initialized - 相機初始化時觸發的事件(事件參數為 CameraOperationCompletedEventArgs 類型)
 *     CaptureStarted - 相機開始捕獲圖片時觸發的事件
 *     CaptureCompleted - 相機捕獲圖片完成時觸發的事件(事件參數為 CameraOperationCompletedEventArgs 類型)
 *     CaptureImageAvailable - 獲得了捕獲到的圖片時觸發的事件(事件參數為 ContentReadyEventArgs 類型)
 *     CaptureThumbnailAvailable - 獲得了捕獲到的圖片的縮略圖時觸發的事件(事件參數為 ContentReadyEventArgs 類型)
 *     
 * 
 * CameraOperationCompletedEventArgs
 *     Succeeded - 操作是否成功
 *     Exception - 異常信息
 *     
 * 
 * ContentReadyEventArgs
 *     ImageStream - 獲取到的圖像流 
 *     
 * 
 * 注:如果要求只使用前置攝像頭的話,則在 manifest 中添加 <Capability Name="ID_HW_FRONTCAMERA"/>
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;

using Microsoft.Devices;
using System.IO;
using System.IO.IsolatedStorage;
using Microsoft.Xna.Framework.Media;
using System.Windows.Navigation;
using System.Windows.Media.Imaging;

namespace Demo.Device.Camera
{
    public partial class ImageDemo : PhoneApplicationPage
    {
        private PhotoCamera _camera;

        // 當前使用的攝像頭分辨率在攝像頭支持的分辨率集合中的索引
        private int _currentResolutionIndex = 0;

        public ImageDemo()
        {
            InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            // 設備是否支持主攝像頭
            if (PhotoCamera.IsCameraTypeSupported(CameraType.Primary))
            {
                // 獲取主攝像頭,並注冊相關事件
                _camera = new PhotoCamera(CameraType.Primary);
                _camera.Initialized += _camera_Initialized;
                _camera.CaptureStarted += _camera_CaptureStarted;
                _camera.CaptureCompleted += _camera_CaptureCompleted;
                _camera.CaptureImageAvailable += _camera_CaptureImageAvailable;
                _camera.CaptureThumbnailAvailable += _camera_CaptureThumbnailAvailable;

                // 在 VideoBrush 上顯示攝像頭捕獲到的實時信息
                videoBrush.SetSource(_camera);

                lblMsg.Text = "設備的主攝像頭正在工作";
            }
            else
            {
                lblMsg.Text = "此設備沒有主攝像頭";

                btnShutter.IsEnabled = false;
                btnFlash.IsEnabled = false;
                btnResolution.IsEnabled = false;
            }
        }

        protected override void OnNavigatingFrom(NavigatingCancelEventArgs e)
        {
            // 釋放相關資源
            if (_camera != null)
            {
                _camera.Dispose();

                _camera.Initialized -= _camera_Initialized;
                _camera.CaptureStarted -= _camera_CaptureStarted;
                _camera.CaptureCompleted -= _camera_CaptureCompleted;
                _camera.CaptureImageAvailable -= _camera_CaptureImageAvailable;
                _camera.CaptureThumbnailAvailable -= _camera_CaptureThumbnailAvailable;
            }
        }

        void _camera_Initialized(object sender, CameraOperationCompletedEventArgs e)
        {
            if (e.Succeeded)
            {
                this.Dispatcher.BeginInvoke(delegate()
                {
                    // 初始化閃光燈模式
                    _camera.FlashMode = FlashMode.Off;
                    btnFlash.Content = "閃光燈:Off";

                    // 初始化分辨率設置
                    _camera.Resolution = _camera.AvailableResolutions.ElementAt<Size>(_currentResolutionIndex);
                    btnResolution.Content = "分辨率:" + _camera.AvailableResolutions.ElementAt<Size>(_currentResolutionIndex);

                    lblMsg.Text = "主攝像頭初始化成功";
                });
            }
        }

        void _camera_CaptureStarted(object sender, EventArgs e)
        {
            // 開始捕獲
            this.Dispatcher.BeginInvoke(delegate()
            {
                lblMsg.Text = "圖片開始捕獲";
            });
        }

        void _camera_CaptureCompleted(object sender, CameraOperationCompletedEventArgs e)
        {
            // 拍照完成
            this.Dispatcher.BeginInvoke(delegate()
            {
                lblMsg.Text = "圖片捕獲完成";
            });
        }

        void _camera_CaptureImageAvailable(object sender, ContentReadyEventArgs e)
        {
            // 獲得了所拍攝的圖片
            this.Dispatcher.BeginInvoke(delegate()
            {
                var bitmapImage = new BitmapImage();
                bitmapImage.SetSource(e.ImageStream);

                imgCapture.Source = bitmapImage;
            });
        }

        public void _camera_CaptureThumbnailAvailable(object sender, ContentReadyEventArgs e)
        {
            // 獲得了所拍攝的圖片的縮略圖
            this.Dispatcher.BeginInvoke(delegate()
            {
                var bitmapImage = new BitmapImage();
                bitmapImage.SetSource(e.ImageStream);

                imgCaptureThumbnail.Source = bitmapImage;
            });
        }

        private void btnShutter_Click(object sender, RoutedEventArgs e)
        {
            if (_camera != null)
            {
                try
                {
                    // 拍攝攝像頭當前捕獲的圖片
                    _camera.CaptureImage();
                }
                catch (Exception ex)
                {
                    lblMsg.Text = "拍攝失敗:" + ex.Message;
                }
            }
        }

        // 攝像頭分辨率的輪換
        private void btnResolution_Click(object sender, RoutedEventArgs e)
        {
            if (++_currentResolutionIndex >= _camera.AvailableResolutions.Count())
                _currentResolutionIndex = 0;

            _camera.Resolution = _camera.AvailableResolutions.ElementAt<Size>(_currentResolutionIndex);
            btnResolution.Content = "分辨率:" + _camera.AvailableResolutions.ElementAt<Size>(_currentResolutionIndex);
        }

        // 閃光燈模式的輪換
        private void btnFlash_Click(object sender, RoutedEventArgs e)
        {
            switch (_camera.FlashMode)
            {
                case FlashMode.Off:
                    if (_camera.IsFlashModeSupported(FlashMode.On))
                    {
                        _camera.FlashMode = FlashMode.On;
                        btnFlash.Content = "閃光燈:On";
                    }
                    break;
                case FlashMode.On:
                    if (_camera.IsFlashModeSupported(FlashMode.RedEyeReduction))
                    {
                        _camera.FlashMode = FlashMode.RedEyeReduction;
                        btnFlash.Content = "閃光燈:RedEyeReduction";
                    }
                    else if (_camera.IsFlashModeSupported(FlashMode.Auto))
                    {
                        _camera.FlashMode = FlashMode.Auto;
                        btnFlash.Content = "閃光燈:Auto";
                    }
                    else
                    {
                        _camera.FlashMode = FlashMode.Off;
                        btnFlash.Content = "閃光燈:Off";
                    }
                    break;
                case FlashMode.RedEyeReduction:
                    if (_camera.IsFlashModeSupported(FlashMode.Auto))
                    {
                        _camera.FlashMode = FlashMode.Auto;
                        btnFlash.Content = "閃光燈:Auto";
                    }
                    else
                    {
                        _camera.FlashMode = FlashMode.Off;
                        btnFlash.Content = "閃光燈:Off";
                    }
                    break;
                case FlashMode.Auto:
                    if (_camera.IsFlashModeSupported(FlashMode.Off))
                    {
                        _camera.FlashMode = FlashMode.Off;
                        btnFlash.Content = "閃光燈:Off";
                    }
                    break;
            }
        }
    }
}


2、演示如何使用攝像頭錄制視頻
VideoDemo.xaml

<phone:PhoneApplicationPage 
    x:Class="Demo.Device.Camera.VideoDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Landscape" Orientation="Landscape"
    mc:Ignorable="d" d:DesignHeight="480" d:DesignWidth="800"
    shell:SystemTray.IsVisible="False">

    <Grid x:Name="LayoutRoot" Background="Transparent">
        <StackPanel Orientation="Vertical">

            <StackPanel Orientation="Horizontal">
                <!--用於實時顯示攝像頭捕獲到的信息-->
                <Canvas Width="320" Height="240">
                    <Canvas.Background>
                        <VideoBrush x:Name="videoBrush" />
                    </Canvas.Background>
                </Canvas>

                <!--用於播放視頻-->
                <MediaElement x:Name="mediaElement" Width="320" Height="240" />
            </StackPanel>

            <StackPanel Orientation="Horizontal">
                <Button x:Name="btnStartRecord" Content="開始錄制" Click="btnStartRecord_Click" />
                <Button x:Name="btnStopRecord" Content="停止錄制" Click="btnStopRecord_Click" />
                <Button x:Name="btnStartPlayback" Content="開始播放" Click="btnStartPlayback_Click" />
                <Button x:Name="btnPausePlayback" Content="暫停播放" Click="btnPausePlayback_Click" />
            </StackPanel>

            <TextBlock Name="lblMsg" />

        </StackPanel>
    </Grid>

</phone:PhoneApplicationPage>

VideoDemo.xaml.cs

/*
 * 演示如何通過攝像頭錄制視頻並保存到獨立存儲,以及如何播放獨立存儲中的視頻
 * 
 * CaptureSource - 操作相關捕獲設備的類
 *     VideoCaptureDevice - 關聯的視頻捕獲設備(System.Windows.Media.VideoCaptureDevice 類型)
 *     AudioCaptureDevice - 關聯的音頻捕獲設備(System.Windows.Media.AudioCaptureDevice 類型)
 *     State - 捕獲的相關狀態(System.Windows.Media.CaptureState 枚舉)
 *         Stopped, Started, Failed
 *     Start() - 啟動關聯的視頻捕獲設備和音頻捕獲設備
 *     Stop() - 關閉關聯的視頻捕獲設備和音頻捕獲設備
 *     CaptureImageAsync() - 異步捕獲圖像
 *     CaptureImageCompleted - 異步捕獲圖像完成后所觸發的事件
 *     CaptureFailed - 捕獲失敗時所觸發的事件
 * 
 * 
 * FileSink - 用於將捕獲到的視頻保存到獨立存儲的類
 *     CaptureSource - 關聯的 CaptureSource 對象
 *     IsolatedStorageFileName - 需要保存到的獨立存儲的地址
 * 
 * 
 * CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice() - 獲取默認的視頻捕獲設備,返回一個 VideoCaptureDevice 對象
 * CaptureDeviceConfiguration.GetAvailableVideoCaptureDevices() - 獲取可用的視頻捕獲設備集合,返回一個 VideoCaptureDevice 對象集合
 * CaptureDeviceConfiguration.GetDefaultAudioCaptureDevice() - 獲取默認的音頻捕獲設備,返回一個 AudioCaptureDevice 對象
 * CaptureDeviceConfiguration.GetAvailableAudioCaptureDevices() - 獲取可用的音頻捕獲設備集合,返回一個 AudioCaptureDevice 對象集合
 * 
 * 
 * VideoCaptureDevice - 用於描述視頻捕獲設備的類
 *     DesiredFormat - 期望的視頻格式
 *     SupportedFormats - 支持的視頻格式
 *     FriendlyName - 設備的名稱
 *     IsDefaultDevice - 是否是視頻捕獲的默認設備
 *     
 * 
 * AudioCaptureDevice - 用於描述音頻捕獲設備的類
 *     AudioFrameSize - 音頻的幀大小(緩沖大小),10 毫秒 - 2000 毫秒之間,默認值是 1000 毫秒
 *     DesiredFormat - 期望的音頻格式
 *     SupportedFormats - 支持的音頻格式
 *     FriendlyName - 設備的名稱
 *     IsDefaultDevice - 是否是音頻捕獲的默認設備
 */

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;

using System.Windows.Navigation;
using System.IO.IsolatedStorage;
using System.IO;

namespace Demo.Device.Camera
{
    public partial class VideoDemo : PhoneApplicationPage
    {
        private CaptureSource _captureSource;
        private FileSink _fileSink;

        // 保存到獨立存儲的視頻的地址
        private string _isoVideoFileName = "myVideo.mp4";
        // 需要播放的獨立存儲中的視頻文件的視頻流
        private IsolatedStorageFileStream _isoVideoFile;
 
        public VideoDemo()
        {
            InitializeComponent();
        }

        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            
            if (_captureSource == null)
            {
                _captureSource = new CaptureSource();
                _captureSource.CaptureFailed += _captureSource_CaptureFailed;

                _fileSink = new FileSink();

                VideoCaptureDevice videoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();
                if (videoCaptureDevice == null)
                {
                    lblMsg.Text = "該設備不支持視頻捕獲";
                }
                else
                {
                    // 讓 VideoBrush 顯示視頻捕獲的實時信息
                    videoBrush.SetSource(_captureSource);
                    // 調用了 CaptureSource.Start() 之后才會開始捕獲視頻
                    _captureSource.Start();

                    lblMsg.Text = "設備正在捕獲視頻中。。。";
                }
            }
        }

        protected override void OnNavigatedFrom(NavigationEventArgs e)
        {
            // 垃圾回收
            DisposeVideoPlayer();
            DisposeVideoRecorder();

            base.OnNavigatedFrom(e);
        }

        private void _captureSource_CaptureFailed(object sender, ExceptionRoutedEventArgs e)
        {
            this.Dispatcher.BeginInvoke(delegate()
            {
                lblMsg.Text = "視頻捕獲失敗:" + e.ToString();
            });
        }

        public void mediaElement_MediaEnded(object sender, RoutedEventArgs e)
        {
            // 視頻播放完成后,重播
            mediaElement.Position = TimeSpan.Zero;
            mediaElement.Play();
        }

        // 清理視頻播放的相關資源
        private void DisposeVideoPlayer()
        {
            // 注:對於那些沒有實現 Dispose() 方法的對象,就把他們設置為 null,這樣垃圾收集器會在需要的時候回收這些對象占用的內存
            
            mediaElement.Stop();
            mediaElement.MediaEnded -= mediaElement_MediaEnded;
            mediaElement.Source = null;

            _isoVideoFile = null;
        }

        // 清理視頻錄制的相關資源
        private void DisposeVideoRecorder()
        {
            // 注:對於那些沒有實現 Dispose() 方法的對象,就把他們設置為 null,這樣垃圾收集器會在需要的時候回收這些對象占用的內存

            if (_captureSource != null)
            {
                if (_captureSource.VideoCaptureDevice != null && _captureSource.State == CaptureState.Started)
                    _captureSource.Stop();

                _captureSource.CaptureFailed -= _captureSource_CaptureFailed;
                _captureSource = null;

                _fileSink = null;
            }
        }

        // 錄制捕獲到的視頻
        private void btnStartRecord_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                // 清除視頻播放的相關資源,因為系統無法同時錄制視頻和播放視頻(也無法同時播放兩個視頻)
                DisposeVideoPlayer();

                if (_captureSource.VideoCaptureDevice != null && _captureSource.State == CaptureState.Started)
                {
                    _captureSource.Stop();

                    // 將 FileSink 與 CaptureSource 做關聯
                    _fileSink.CaptureSource = _captureSource;
                    // 設置錄制好的視頻所需保存到的獨立存儲的地址
                    _fileSink.IsolatedStorageFileName = _isoVideoFileName;
                }

                if (_captureSource.VideoCaptureDevice != null && _captureSource.State == CaptureState.Stopped)
                {
                    // 開始捕獲,如果關聯了 FileSink,則會將捕獲到的視頻流以流的方式寫入到指定的獨立存儲地址
                    _captureSource.Start();
                }

                lblMsg.Text = "開始錄制視頻";
            }
            catch (Exception ex)
            {
                lblMsg.Text = "開始錄制視頻失敗:" + ex.ToString();
            }
        }

        // 停止錄制
        private void btnStopRecord_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                if (_captureSource.VideoCaptureDevice != null && _captureSource.State == CaptureState.Started)
                {
                    _captureSource.Stop();

                    // 清空 FileSink 的相關聯信息
                    _fileSink.CaptureSource = null;
                    _fileSink.IsolatedStorageFileName = null;
                }

                lblMsg.Text = "停止錄制視頻";
            }
            catch (Exception ex)
            {
                lblMsg.Text = "停止錄制視頻失敗:" + ex.ToString();
            }
        }

        // 播放視頻
        private void btnStartPlayback_Click(object sender, RoutedEventArgs e)
        {
            if (_isoVideoFile != null)
            {
                mediaElement.Play();
            }
            else
            {
                // 停止視頻捕獲,因為系統無法同時錄制視頻和播放視頻(也無法同時播放兩個視頻)
                _captureSource.Stop();

                _isoVideoFile = new IsolatedStorageFileStream(_isoVideoFileName, FileMode.Open, FileAccess.Read, IsolatedStorageFile.GetUserStoreForApplication());

                // 用 MediaElement 播放獨立存儲中的指定視頻
                mediaElement.SetSource(_isoVideoFile);
                mediaElement.MediaEnded += mediaElement_MediaEnded;
                mediaElement.Play();
            }

            lblMsg.Text = "開始播放視頻";
        }

        // 暫停播放視頻
        private void btnPausePlayback_Click(object sender, RoutedEventArgs e)
        {
            mediaElement.Pause();

            lblMsg.Text = "暫停播放視頻";
        }
    }
}



OK
[源碼下載]


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM