有关 Nokia Imaging SDK 的初级使用,可以参考:Nokia Imaging SDK滤镜使用入门

本文的主题:

1、如何 PhotoCaptureDevice 类使用,以及如何在 MediaElement 控件上显示摄像头预览。

2、如何通过 Nokia Imaging SDK 提供的滤镜,运用到摄像头的预览缩略图图片流上。相片拍照完成后

,再为高像素图片运用用户选择的滤镜效果。

3、通过本工程,开发者可以快速预览 Nokia Imaging SDK 所提供 53 种滤镜 的大致效果,可以在

实际的开发过程中,快速选择相应的滤镜进行使用。

本文的内容:

1、首先提供一个基本的代码架构(basic文件夹下)。接下来的步骤是基于这个基本代码工程进行操作的。“基本代码工程”

实现了照片拍摄(使用 WP8 中的高级拍照 PhotoCaptureDevice 类)的基本功能,拍照完成后跳转到照片预览页面。

基本代码的运行如图:

注意:本文不会对讲述 PhotoCaptureDevice 类的使用。参考 MSDN

2、打开 basic 文件夹下的基本工程。在基本工程里面,已经添加好 Nokia Imaging SDK的相关类库。

工程目录及相关类和页面功能的说明:

3、因为工程完成后的代码量较大,为了更好的完成本工程,先介绍一下下面步骤将实现的功能。

1)单击屏幕,显示滤镜选择列表。包括 Nokia Imaging SDK 提供的 53个滤镜。

2)从滤镜列表选择滤镜后,摄像头取景框实时显示:

3)单击拍摄按钮,从 MainPage.xaml 页面跳转到ImagePreviewPage.xaml ,显示经过滤镜处理的图片(截图选择的是“魔术笔滤镜”):

4、在工程的根目录下新建一个文件夹“FilterComponent”,用来存储接下来的代码文件。

5、因为 MediaElement 有两个方法:

public void SetSource(MediaStreamSource mediaStreamSource);

public void SetSource(Stream stream);

这里我们使用第一个方法。

在 FilterComponent 文件夹下新建一个 CameraStreamSource类,该类继承自 MediaStreamSource类。把这个CameraStreamSource

类用来作为 MediaElement 控件的数据源。

注:这里只列出重点方法的解释,并未贴出全部代码及注释。具体代码请查看Code_Snippets文件夹下的 CameraStreamSource.cs 文件。

6、重写上面定义的CameraStreamSource类中的两个重要方法:

protected override void OpenMediaAsync()
protected override void GetSampleAsync(MediaStreamType mediaStreamType)

1)OpenMediaAsync 方法:收集实例化 MediaStreamDescription 对象的集合所需的元数据,然后对其进行实例化。可以把这个方法理解成,

当初始化为 MediaElement 视频流时会调用 OpenMediaAsync(),在这个方法里面,设置流数据信息,包括了流数据,视频宽高,视频时间,

当初始化完成后,调用 ReportOpenMediaCompleted(mediaSourceAttributes, mediaStreamDescriptions) 方法,来通知 MediaElement

控件,MediaStreamSource已经打开,并提供相关视频流信息。该方法仅会在视频信息初始化时调用一次。

具体的解释可以参考工程的代码注释。

2)GetSampleAsync 方法:导致 MediaStreamSource 准备一个 MediaStreamSample,它描述要由媒体管线呈现的下一个媒体示例。可以通过 ReportGetSampleCompleted 和 ReportGetSampleProgress 响应此方法。当为 MediaElement 控件提供视频流的每一帧时调用,此时我们能够

获得图像的帧数据,此时我们为该帧添加用户选择的滤镜效果。

7、在 FilterComponent 文件夹下,新建一个 FilterItem 类,该类有5个成员:

 public class FilterItem
{
public int Index { get; set; }
public string Name { get; set; } /// <summary>
/// 引用当前用户选择的滤镜效果
/// </summary>
public static FilterItem CurrentFilterItem { get; set; } /// <summary>
/// 创建滤镜效果
/// </summary>
/// <param name="index">当 index 不为空时,设置 index 指定的滤镜,如果为空,则指定
/// CurrentFilterItem.Index 指定的滤镜</param>
/// <returns></returns>
public static List<IFilter> CreateInstance(int? index = null)
{

} /// <summary>
/// 滤镜列表数据源
/// </summary>
public static readonly List<FilterItem> FilterSource = new List<FilterItem>
{

}
}

该类的作用是为 MainPage 页面的滤镜列表提供数据源。其中CreateInstance() 方法通过Switch 语句来创建相应的滤镜实体。

注:这里只列出重点方法的解释,并未贴出全部代码及注释。具体代码请查看Code_Snippets文件夹下的 FilterItem.cs 文件。

8、在 FilterComponet 文件夹下,新建一个 NokiaImagingSDKEffects 类,在这个类中,我们主要添加一个

public async Task GetNewFrameAndApplyEffect(IBuffer frameBuffer, Size frameSize)

该方法的作用是为预览视频流的帧添加滤镜。该方法的全部代码:

/// <summary>
/// 为预览视频流的帧添加滤镜
/// </summary>
/// <param name="frameBuffer">帧数据</param>
/// <param name="frameSize">帧尺寸</param>
/// <returns></returns>
public async Task GetNewFrameAndApplyEffect(IBuffer frameBuffer, Size frameSize)
{
var scanlineByteSize = (uint)frameSize.Width * ; // 4 bytes per pixel in BGRA888 mode
var bitmap = new Bitmap(frameSize, ColorMode.Bgra8888, scanlineByteSize, frameBuffer); // 通过 _photoCaptureDevice 创建一个新的 image source
_cameraPreviewImageSource = new CameraPreviewImageSource(_photoCaptureDevice); if (FilterItem.CurrentFilterItem != null)
{
_filterEffect = new FilterEffect(_cameraPreviewImageSource)
{
Filters = FilterItem.CreateInstance()
}; var renderer = new BitmapRenderer(_filterEffect, bitmap);
await renderer.RenderAsync();
}
else
{
var renderer = new BitmapRenderer(_cameraPreviewImageSource, bitmap);
await renderer.RenderAsync();
}
}

注:这里只列出重点方法的解释,并未贴出全部代码及注释。具体代码请查看Code_Snippets文件夹下的 NokiaImagingSDKEffects.cs 文件。

9、在 FilterComponent 文件夹下创建一个 MainPage_Realtime.cs 文件,该文件存放的类是 MainPage 类的分部类,使用关键字 partial

关键字把新代码和基础代码工程的 MainPage 类进行区分:

public partial class MainPage : PhoneApplicationPage
{

}

在该文件中添加三个全局变量:

private MediaElement _mediaElement = null;
private NokiaImagingSDKEffects _cameraEffect = null;
private CameraStreamSource _cameraStreamSource = null;

并添加一个 InitializeEffect() 方法来初始这些变量。

10、修改 MainPage 类。

1)为 MainPage.xaml 页面中,DataTemplate 中为 Image 控件添加一个 Loaded 事件,当该控件加载完成后,添加预览滤镜图片:

<Image Loaded="Image_Loaded"/>

MainPage_Realtime.cs 文件中添加该 Image_Loaded 方法:

/// <summary>
/// 当滤镜列表模版中的 Image 加载完成后,添加相应的滤镜预览图
/// </summary>
private async void Image_Loaded(object sender, RoutedEventArgs e)
{
Image image = sender as Image; // 读取根目录下的示例图片
Stream _imageSource = App.GetResourceStream(new Uri("Sample.jpg", UriKind.Relative)).Stream; // 获取当前 Item 的 DataContext
FilterItem item = image.DataContext as FilterItem; WriteableBitmap writeableBitmap = new WriteableBitmap(, ); // 为示例图片添加相应的滤镜效果
using (var source = new StreamImageSource(_imageSource))
using (var filterEffect = new FilterEffect(source) { Filters = FilterItem.CreateInstance(item.Index).ToArray() })
using (var renderer = new WriteableBitmapRenderer(filterEffect, writeableBitmap))
{
await renderer.RenderAsync();
} // 显示到页面中
image.Source = writeableBitmap;
}

2)在 MainPage.xaml 页面,为 ListBox 中 DataTemplate 模版中的 Border 控件添加  Tap="Border_Tap" 事件,来把用户选择的滤镜效

果设置为全局共享变量,该事件在 MainPage 的分部类中实现:

/// <summary>
/// 用户单击滤镜列表中的滤镜项
/// </summary>
private void Border_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
//e.Handled = true; FilterItem.CurrentFilterItem = (sender as Border).DataContext as FilterItem;
}

2)在 MainPage.xaml 给名为 LayoutRoot 的 grid 添加一个 Tap="LayoutRoot_Tap"   事件,来动态切换滤镜列表的显示与隐藏,

该事件在 MainPage 的分部类中实现:

/// <summary>
/// 单击屏幕时,切换滤镜列表
/// </summary>
private void LayoutRoot_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
e.Handled = true; if (listbox_preview.Visibility == System.Windows.Visibility.Collapsed)
{
listbox_preview.Visibility = System.Windows.Visibility.Visible;
}
else
{
listbox_preview.Visibility = System.Windows.Visibility.Collapsed;
}
}

3)添加完上面代码,在 MainPage.xaml.cs 文件中,修改 OnNavigatedTo() 方法,把 BackgroundVideoBrush.SetSource(_photoCaptureDevice);

替换为 MainPage 分部类种添加的 InitializeEffect(); 当页面导航到 MainPage 页面后,初始化相应的控件和滤镜。

同样,在 OnNavigatingFrom() 中,添加 MainPage分部类 中的 Uninitialize_Realtime();方法,以当页面导航离开时,释放资源。

注:这里只列出重点方法的解释,并未贴出全部代码及注释。具体代码请查看Code_Snippets文件夹下的 MainPage_Realtime.cs 文件。

11、ImagePreviewPage.xaml.cs 页面中,为 PhotoCaptureDevice 类捕获的高分辨率图片添加用户选择的滤镜效果。因为高分辨率图片保存在了 ImageDataContext.Singleton.ImageStream  属性中,所以直接对它添加滤镜效果,然后显示在页面上:

protected override async void OnNavigatedTo(NavigationEventArgs e)
{
ImageDataContext dataContext = ImageDataContext.Singleton; if (dataContext.ImageStream != null)
{
// 显示默认没有滤镜效果的图片
//BitmapImage bi = new BitmapImage();
//bi.SetSource(dataContext.ImageStream);
//image.Source = bi; dataContext.ImageStream.Seek(, SeekOrigin.Begin);//严重注意!!!!!!!! using (var source = new StreamImageSource(dataContext.ImageStream))
using (var filterEffect = new FilterEffect(source) { Filters = FilterItem.CreateInstance() })
using (var renderer = new JpegRenderer(filterEffect))
{
Windows.Storage.Streams.IBuffer buf = await renderer.RenderAsync(); Stream stream = System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeBufferExtensions.AsStream(buf);
BitmapImage bi = new BitmapImage();
bi.SetSource(stream);
image.Source = bi;
}
} base.OnNavigatedTo(e);
}

代码工程完成后,运行效果:

上面的 gif 图片快速演示了 Nokia Imging SDK 中的 53 种滤镜,并且给取景器快速运用其中对比比较明显的几个滤镜,拍照

后,即可得到经过滤镜处理的全像素照片。

总结:

本实验代码量比较多,没有全部粘贴工程代码,而是先在 basic 文件夹下提供一个用 PhotoCaptureDeVice类实现的拍

照功能的基本代码工程,然后在该文件夹下的 Code_Snippets 文件夹中,提供相应的代码片段。动手实验文档中主要讲解了重点代码的作用,

并且 Nokia Imaging SDK 提供的 全部 53种滤镜,都只是设置了默认值,具体参数的调整已经添加到工程的代码注释上。

有关 Nokia Imaging SDK 滤镜使用流程,请参考相关文档

代码工程下载:http://pan.baidu.com/s/1sj4RKo1

提示:

1、因为本实验会使用到手机摄像头,所以建议通过真机调试

2、在运行源代码时,会出现一个编译错误: Nokia Imaging SDK does not support the AnyCPU target platform.

因为 Nokia Imaging SDK 支持托管代码和本地代码,所以在编译前需要进行设置:

1)在模拟器上运行时:菜单 -> 生成 -> 配置管理器 -> 活动解决方案平台 -> x86 2)在真机上运行时:  菜单 -> 生成 -> 配置管理器 -> 活动解决方案平台 -> ARM

更多有关说明请参考: http://developer.nokia.com/Resources/Library/Lumia/#!nokia-imaging-sdk/adding-libraries-to-the-project.html

Nokia Imaging SDK 的高级使用—实时滤镜拍照的更多相关文章

  1. 使用 Nokia Imaging SDK 开发有滤镜功能的 Windows Phone 8 应用

    说到滤镜应用,相信很多数开发者都对照片特效的经验都十分有限,通常都是去找一些三方的类库进行学习或移植,今天在这里给大家介绍下 Nokia 的 Imaging SDK, 相信大家对Nokia的自家图像软 ...

  2. Nokia Imaging SDK滤镜使用入门

    简要说明: 通过对示例图片分别运用 LomoFilter和SketchFilter两个滤镜(Nokia Imaging SDK 内置), 来学习滤镜的基本使用和参数的设置.本工程的代码量比较少,也很容 ...

  3. Nokia Imaging SDK

    Nokia Imaging SDK 目前为 beta 版本,是诺基亚在自己的图像应用中使用的技术同时提供给开发者 使用.这是一个运行在手机设备上处理图片数据的高效的类库.功能包括 JEPG 图片的编码 ...

  4. GPUimage实时滤镜的实现

    GPUIMAGE中GPUImageStillCamera可以调用系统相机,并实现实时滤镜,但是我没有找到相机全屏的方法,望知道的说一下 GPUImageStillCamera继承自GPUImageVi ...

  5. 导入GPUImage,实时滤镜相机,GUPImage遇到的问题解决,_OBJC_METACLASS_$_GBGPUImageView in GBGPUImageView.o

    导入方法转自:http://www.cnblogs.com/S2-huai/p/3881349.html.. (原文:http://www.cnblogs.com/YouXianMing/p/3709 ...

  6. iOS8 Core Image In Swift:视频实时滤镜

    iOS8 Core Image In Swift:自己主动改善图像以及内置滤镜的使用 iOS8 Core Image In Swift:更复杂的滤镜 iOS8 Core Image In Swift: ...

  7. Android平台Camera实时滤镜实现方法探讨(三)--通过Shader实现YUV转换RBG

    http://blog.csdn.net/oshunz/article/details/50055057 文章例如该链接通过将YUV分成三个纹理,在shader中取出并且经过公式变换,转换成RGB.我 ...

  8. Android平台Camera实时滤镜实现方法探讨(十)--代码地址以及简单介绍(20160118更新)

    简单做了个相机和图片编辑模块,时间原因非常多功能还没有做.尚有BUG,见谅,将在以后抽时间改动 代码地址 PS:请点个Star^-^ --------------------------------- ...

  9. Android平台Camera实时滤镜实现方法探讨(十一)--实时美颜滤镜

    上一章完毕了对图片的磨皮处理.经过简单算法流程优化,能够达到非常快的速度.可是不能用于实时美颜.经实验,若採用仅仅处理Y信号的方案.半径极限大约是5-10,超过10则明显感受到卡顿.但对于1920X1 ...

随机推荐

  1. 【帧动画总结】AnimationDrawable Frame

    Drawable Animation 开发者文档 位置:/sdk/docs/guide/topics/graphics/drawable-animation.html Drawable animati ...

  2. CentOS7 rpm方式安装mysql5.7

    内容源自:CentOS7安装mysql 在CentOS中默认安装有MariaDB,这个是MySQL的分支,但为了需要,还是要在系统中安装MySQL,而且安装完成之后可以直接覆盖掉MariaDB. 1. ...

  3. 转:Eclipse ADT的Custom debug keystore所需证书规格

    转:http://blog.k-res.net/archives/1229.html Eclipse ADT的Custom debug keystore所需证书规格 三月 8, 2013  |  Po ...

  4. 使用javascript开发的视差滚动效果的云彩 极客标签 - 做最棒的极客知识分享平台

    www.gbtags.com 使用javascript开发的视差滚动效果的云彩 阅读全文:使用javascript开发的视差滚动效果的云彩 极客标签 - 做最棒的极客知识分享平台

  5. java梳理-一个汉字占多大空间

    面试题:一个汉字占多大空间. 事实上这个问题我了解不深的,知道结论不知道为什么.借此梳理下认识. 先回想下java基本类型 一基本类型 :简称四类八种,声明变量的同一时候分配了空间.举比例如以下:   ...

  6. C#基础视频教程4.2 如何编写简单的计算器

    用过VB6或者早期代码的人都应该能感觉到,C#目前也没看出来有什么特别之处,所谓的面向对象也没有什么体现.所以我们需要在原有基础上重写一份代码,然后比较两种做法的优缺点.我们在项目上右击添加一个Fun ...

  7. 裸裸的线段树(hdu 1754)

    线段树的第一发. 哪天忘了还能够让自己找找回顾. 线段树操作: build  : 建树. update:点改动: query:查询 Input 在每一个測试的第一行,有两个正整数 N 和 M ( 0& ...

  8. android开发之MediaPlayer+Service MP3播放器

    import java.io.File; import java.io.FilenameFilter; import java.util.ArrayList; import java.util.Lis ...

  9. TCP协议中的SO_LINGER选项

    TCP协议中的SO_LINGER选项 SO_LINGER选项用来设置延迟关闭的时间,等待套接字发送缓冲区中的数据发送完成.没有设置该选项时,在调用close()后,在发送完FIN后会立即进行一些清理工 ...

  10. send返回值

    http://blog.csdn.net/anghlq/article/details/5990513 在Unix系统下,如果send . recv . write在等待协议传送数据时 , socke ...