与众不同 windows phone (21) - Device(设备)之摄像头(拍摄照片, 录制视频)

时间:2023-03-08 23:01:09
与众不同 windows phone (21) - Device(设备)之摄像头(拍摄照片, 录制视频)

原文:与众不同 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 = ; 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 = ; _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
[源码下载]