Nokia Imaging SDK 的高级使用—实时滤镜拍照
有关 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
Nokia Imaging SDK 的高级使用—实时滤镜拍照的更多相关文章
- 使用 Nokia Imaging SDK 开发有滤镜功能的 Windows Phone 8 应用
说到滤镜应用,相信很多数开发者都对照片特效的经验都十分有限,通常都是去找一些三方的类库进行学习或移植,今天在这里给大家介绍下 Nokia 的 Imaging SDK, 相信大家对Nokia的自家图像软 ...
- Nokia Imaging SDK滤镜使用入门
简要说明: 通过对示例图片分别运用 LomoFilter和SketchFilter两个滤镜(Nokia Imaging SDK 内置), 来学习滤镜的基本使用和参数的设置.本工程的代码量比较少,也很容 ...
- Nokia Imaging SDK
Nokia Imaging SDK 目前为 beta 版本,是诺基亚在自己的图像应用中使用的技术同时提供给开发者 使用.这是一个运行在手机设备上处理图片数据的高效的类库.功能包括 JEPG 图片的编码 ...
- GPUimage实时滤镜的实现
GPUIMAGE中GPUImageStillCamera可以调用系统相机,并实现实时滤镜,但是我没有找到相机全屏的方法,望知道的说一下 GPUImageStillCamera继承自GPUImageVi ...
- 导入GPUImage,实时滤镜相机,GUPImage遇到的问题解决,_OBJC_METACLASS_$_GBGPUImageView in GBGPUImageView.o
导入方法转自:http://www.cnblogs.com/S2-huai/p/3881349.html.. (原文:http://www.cnblogs.com/YouXianMing/p/3709 ...
- iOS8 Core Image In Swift:视频实时滤镜
iOS8 Core Image In Swift:自己主动改善图像以及内置滤镜的使用 iOS8 Core Image In Swift:更复杂的滤镜 iOS8 Core Image In Swift: ...
- Android平台Camera实时滤镜实现方法探讨(三)--通过Shader实现YUV转换RBG
http://blog.csdn.net/oshunz/article/details/50055057 文章例如该链接通过将YUV分成三个纹理,在shader中取出并且经过公式变换,转换成RGB.我 ...
- Android平台Camera实时滤镜实现方法探讨(十)--代码地址以及简单介绍(20160118更新)
简单做了个相机和图片编辑模块,时间原因非常多功能还没有做.尚有BUG,见谅,将在以后抽时间改动 代码地址 PS:请点个Star^-^ --------------------------------- ...
- Android平台Camera实时滤镜实现方法探讨(十一)--实时美颜滤镜
上一章完毕了对图片的磨皮处理.经过简单算法流程优化,能够达到非常快的速度.可是不能用于实时美颜.经实验,若採用仅仅处理Y信号的方案.半径极限大约是5-10,超过10则明显感受到卡顿.但对于1920X1 ...
随机推荐
- 如何利用Flink实现超大规模用户行为分析
如何利用Flink实现超大规模用户行为分析 各位晚上好,首先感谢大家参与我的这次主题分享,同时也感谢 InfoQ AI 前线组织这次瀚思科技主题月! 瀚思科技成立于 2014 年,按行业划分我们是 ...
- STM32+IAP方案 实现网络升级应用固件
关注了这个概念有些日子了,这段时间总算有机会实战==网络升级应用固件,这里记录下遇到的问题,及解决方案. 原理与网上流传的串口作为传输手段 一致:不同之处,无非我这里使用了网络设备传输.==(lwip ...
- Servlet介绍以及简单实例
一.背景介绍: HTTP:超文本传输协议(HTTP,HyperText Transfer Protocol)是互联网上应用最为广泛的一种网络协议.设计HTTP最初的目的是为了提供一种发布和接收 HTM ...
- Visual Studio 2015年预览设置: 辅助安装程序说明
本文介绍了第三方应用程序安装辅助安装的 Visual Studio 2015年预览时安装的说明.如果您安装了多设备开发功能,您需要使用其他第三方软件来处理这些项目.辅助安装程序允许您将部署到您的计算机 ...
- ASP服务器I I S出现authentication mode=Windows错误解决办法
网上下载的asp.net源码出现 <authentication mode="Windows"/>错误信息 属性 说明 mode 必选的属性. 指定应用程序的默认身份验 ...
- ionic的加载功能
下面是代码(黄色背景的是加载功能的代码): <html ng-app="ionicApp"> <head> <meta charset="u ...
- cscope无法索引代码树之外的软链接
http://blog.csdn.net/sudolee/article/details/9052291 背景:为什么非要使用cscope?不用ctags? 尽管ctags可以索引软链接,但是,cta ...
- 关于npm本地安装模块包(node_modules),安装不了的问题
单独测试的时候,发现安装不了node_modules包 缺少package.json,无法安装. 分为以下两步: 1.npm init -y 2.npm i -D vue 或 yarn add vue
- JSP生成静态html网页
/** * jsp生成静态html网页 */ public class ToHtml extends HttpServlet { public void service(HttpServletRequ ...
- com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "ExceptionId"
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "Exception ...