从第4版开始Silverlight支持摄像头和麦克风的使用,给网络多媒体展示提供了新的设计空间。
图4-17是摄像头使用的示例。
图4-17中上方是1个TextBlock(textblock1)文本控件,用于显示信息。左上方是1个Rectangle(rectangle)控件用于显示捕获的摄像头视频,右上方是1个ListBox控件(listbox)用于显示截取的多张静态图像,右下方的Grid布局控件中是Image(p_w_picpath)控件用于显示当前截取的静态图片,4个按钮“启动摄像头”(button1)、“截取静态图”(button2)、“关闭摄像头”(button3)和“保存为JPG”(JPEG格式,button4)的Click事件的代码如下。
在.xaml.cs文件的开始添加了引用:
using System.Windows.Media.Imaging;//for WriteableBitmap
using System.IO;//for Stream
同时定义了一些摄像头捕获动态图像使用的变量:
//定义摄像设备
public VideoCaptureDevice camera;
//创建捕获源对象
public CaptureSource capturesource = new CaptureSource();
//创建视频刷
public VideoBrush videoBrush = new VideoBrush();
摄像头捕获动态图形的基本设计过程是:获取摄像设备—设置捕获源对象—设置视频刷—填充矩形显示。
图4-17 摄像头使用示例
- “启动摄像头”:
- private void button1_Click(object sender, System.Windows.RoutedEventArgs e)
- {
- StartCamera();//摄像设备启动自定义程序
- //如果允许启用获取的摄像头
- if (CaptureDeviceConfiguration.RequestDeviceAccess())
- {
- capturesource.Start();//开始摄像
- this.button2.IsEnabled=true;
- this.button3.IsEnabled=true;
- }
- }
- 其中StartCamera()的代码是:
- private void StartCamera(){
- //检测摄像头
- VideoCaptureDevice cameradevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();
- //如果没有配置摄像头
- if (cameradevice == null){
- this.textblock1.Text="没有可用的视频摄像头!";
- this.button1.IsEnabled=false;
- }
- else{
- this.textblock1.Text="检测到摄像头:"+cameradevice.FriendlyName;
- //获取本机摄像头
- camera = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice();
- //设置捕获源对象设备为摄像头
- capturesource.VideoCaptureDevice = camera;
- //设置视频刷源
- videoBrush.SetSource(capturesource);
- //利用视频刷填充矩形对象
- this.rectangle.Fill = videoBrush;
- }
- }
- “截取静态图”:
- 这里仅仅是截取静态图形显示。
- private void button2_Click(object sender, System.Windows.RoutedEventArgs e)
- {
- //截取静态图片及相应事件处理
- this.capturesource.CaptureImageAsync();
- this.capturesource.CaptureImageCompleted += (ss, se) =>
- {
- if (se.Error == null)
- {
- this.p_w_picpath.Source = se.Result;
- WriteableBitmap bitmap =se.Result; //定义位图对象
- Image p_w_picpath1 = new Image();
- p_w_picpath1.Width=160;
- p_w_picpath1.Stretch=Stretch.Fill;
- p_w_picpath1.Source=bitmap; //设置Image对象源,显示图形
- this.listbox.Items.Add(p_w_picpath1);
- this.button4.IsEnabled=true;
- }
- else{
- this.textblock1.Text = se.Error.Message;
- return;
- }
- };
- }
- 其中this.capturesource.CaptureImageAsync()是启动截取源对象的方法,当截取完成时会自动执行this.capturesource.CaptureImageCompleted事件代码。
- WriteableBitmap类提供了1个位图操作源,可以用于Image的显示源,也可以用于图形刷ImageBrush的图形源设置。
- “保存为JPG”(JPEG格式):
- 这里将显示在p_w_picpath中的图形保存为JPEG格式文件,文件名和路径是对话框选择的。
- private void button4_Click(object sender, System.Windows.RoutedEventArgs e)
- {
- //创建对象,源来自iamge
- WriteableBitmap bitmap = new WriteableBitmap(p_w_picpath, null);
- //保存文件
- if (bitmap != null)
- {
- SaveFileDialog saveJPEG = new SaveFileDialog();
- saveJPEG.Filter = "JPEG Files (*.jpeg)|*.jpeg";
- if (saveJPEG.ShowDialog().Value)
- {
- thisthis.textblock1.Text=this.textblock1.Text+" 保存文件:"+saveJPEG.SafeFileName;
- using (Stream jpegstream = saveJPEG.OpenFile())
- {
- SaveToJPEGFile(bitmap, jpegstream);
- }
- }
- }
- }
- 其中调用的SaveToJPEGFile(bitmap, jpegstream)方法中应用了1个网上下载的库函数“FJ.Core.dll”,其功能是可以对位图数据进行色彩、编码处理,变为JPEG格式,给程序设计提供了方便。这样,需要在客户端的项目“引用”中“添加引用”,选中“FJ.Core.dll”,实例中已经提供了这个库函数。感谢库函数的作者。
- private static void SaveToJPEGFile(WriteableBitmap bitmap, Stream jpegstream)
- {
- int width = bitmap.PixelWidth; //获取p_w_picpath信息
- int height = bitmap.PixelHeight;
- int unitrow = 3;
- byte[][,] lattice = new byte[unitrow][,];
- //建立图形区
- for (int i = 0; i < unitrow; i++)
- {
- lattice [i] = new byte[width, height];
- }
- for (int row = 0; row < height; row++)
- {
- for (int column = 0; column < width; column++)
- {
- int pixel = bitmap.Pixels[width * row + column];
- lattice [0][column, row] = (byte)(pixel >> 16);
- lattice [1][column, row] = (byte)(pixel >> 8);
- lattice [2][column, row] = (byte)pixel;
- }
- }
- //应用FJ.Core.dll中的类处理,色彩处理
- FluxJpeg.Core.ColorModel colormodel = new FluxJpeg.Core.ColorModel { colorspace = FluxJpeg.Core.ColorSpace.RGB };
- FluxJpeg.Core.Image p_w_picpath2 = new FluxJpeg.Core.Image(colormodel, lattice);
- MemoryStream stream = new MemoryStream();//将p_w_picpath2编码为JPEG
- FluxJpeg.Core.Encoder.JpegEncoder jpegencoder = new FluxJpeg.Core.Encoder.JpegEncoder(p_w_picpath2, 100, stream);
- jpegencoder.Encode();
- stream.Seek(0, SeekOrigin.Begin); //回到stream的初始位置
- byte[] buffer = new Byte[stream.Length]; //定义缓存区
- //获取jpeg数据流,读入缓存
- long bytesRead = stream.Read(buffer, 0, (int)stream.Length);
- jpegstream.Write(buffer, 0, buffer.Length); //写入文件流
- }
- “关闭摄像头”:
- private void button3_Click(object sender, System.Windows.RoutedEventArgs e)
- {
- capturesource.Stop();
- this.rectangle.Fill=null;
- this.button2.IsEnabled=false;
- this.button3.IsEnabled=false;
- this.button4.IsEnabled=false;
- }