zoukankan      html  css  js  c++  java
  • Nokia Imaging SDK滤镜使用入门

    简要说明

    通过对示例图片分别运用 LomoFilterSketchFilter两个滤镜(Nokia Imaging SDK 内置),

    来学习滤镜的基本使用和参数的设置。本工程的代码量比较少,也很容易理解。

    版本 NokiaImagingSDK  1.0.272.0

    下面是这个 demo 的完成步骤:

    1)通过 Visual Studio 2012 新建一个Windows Phone 8 的工程,命名为“FilterParametersSample”:

    2) 右键单击工程的“引用”,选择“管理 NuGet程序包”:

    在右上角搜索框输入“Nokia Imaging SDK”,并安装该 SDK:

    3)因为本次实验使用模拟器调试,所以需要在“配置管理器”选择“x86”(Visual Studio菜单 -> 生成 -> 配置管理器):

    注:关于添加 Nokia Imaging SDK后 VS 的设置请参考:Download and add the libraries to the project

    4)在项目的根目录下添加一张示例图片 “Sample.jpg”:

    5)在 MainPage.xaml 页面中添加一个 Image 控件(显示原图)和两个 Button 控件,单击 Button 后,分别跳转

    到 LomoFilterPage.xaml 和 SketchFilterPage.xaml页面。用下面的 XAML 替换掉 MainPage 页面中名为 LayoutRoot 的 grid:

     <!--LayoutRoot 是包含所有页面内容的根网格-->
        <Grid x:Name="LayoutRoot" Background="Transparent">
            <Image Source="/Sample.jpg" Margin="117,82,89,231"/>
            <Button Content="LomoFilter" HorizontalAlignment="Left" Margin="25,669,0,0" VerticalAlignment="Top" 
    Width
    ="209" Click="LomoFilter_Button_Click"/> <Button Content="Sketch" HorizontalAlignment="Left" Margin="239,669,0,0"
    VerticalAlignment
    ="Top" Width="205" Click="SketchFilter_Button_Click"/> </Grid>

    在 MainPage.xaml.cs 页面添加相应的按钮事件:

            // Lomo (自由滤镜)
            private void LomoFilter_Button_Click(object sender, RoutedEventArgs e)
            {
                NavigationService.Navigate(new Uri("/Pages/LomoFilterPage.xaml", UriKind.Relative));
            }
    
            // Sketch 素描滤镜
    private void SketchFilter_Button_Click(object sender, RoutedEventArgs e) { NavigationService.Navigate(new Uri("/Pages/SketchFilterPage.xaml", UriKind.Relative)); }


    6)新建一个名为“Pages”的文件夹,在页面中分别添加两个页面:

    LomoFilterPage.xaml SketchFilterPage.xaml,分别用来处理 Lomo 滤镜和 Sketch滤镜。

    7)首先打开 SketchFilterPage.xaml 页面,在 XAML 页面添加一个 Image 控件和两个RadioButton 控件,

    分别用来显示预览图和切换滤镜模式:

    <Grid x:Name="LayoutRoot" Background="Transparent" Tap="LayoutRoot_Tap">
         <Image x:Name="PreviewImage"/>
    
         <Grid x:Name="gridControls" VerticalAlignment="Bottom" Background="#44ffffff" >
             <Grid.Resources>
                 <Style TargetType="TextBlock">
                     <Setter Property="Margin" Value="20,0,0,0"/>
                     <Setter Property="Foreground" Value="#ffffffff"/>
                     <Setter Property="FontWeight" Value="ExtraBold"/>
                 </Style>
             </Grid.Resources>
             <Grid.RowDefinitions>
                 <RowDefinition Height="auto"/>
                 <RowDefinition Height="auto"/>
             </Grid.RowDefinitions>
    
             <TextBlock Text="素描模式:"/>
             <StackPanel Orientation="Horizontal" Grid.Row="1" Background="{StaticResource PhoneAccentBrush}">
                 <RadioButton Content="Gray" GroupName="Mode"  Checked="Gray_RadioButton_Checked"/>
                 <RadioButton Content="Color" GroupName="Mode" Checked="Color_RadioButton_Checked"/>
             </StackPanel>
         </Grid>
     </Grid>

    上面的 gridControls 用来作为“操作面板”,当单击 LayoutRoot 控件时,切换它的隐藏和显示:

    // 切换控制面板
      private void LayoutRoot_Tap(object sender, System.Windows.Input.GestureEventArgs e)
      {
          e.Handled = true;
          if (gridControls.Visibility == System.Windows.Visibility.Collapsed)
          {
              gridControls.Visibility = System.Windows.Visibility.Visible;
          }
          else
          {
              gridControls.Visibility = System.Windows.Visibility.Collapsed;
          }
      }     


    8)另外在 SketchFilterPage.xaml.cs 页面中,声明三个变量:

    // 使用滤镜
    SketchMode _sketchMode = SketchMode.Gray;
    Stream _imageStreamOrigin;// 保存图片的原始数据
    WriteableBitmap _writeBitmap; //输出结果


    9)在构造函数中,读取示例图片的流,用来稍后添加滤镜:

    public SketchFilterPage()
     {
         InitializeComponent();
    
         // 获取 xap 包中的 图片
         StreamResourceInfo StreamInfo = App.GetResourceStream(new Uri("Sample.jpg", UriKind.Relative));
    
         // 先把未经过滤镜处理的示例图片显示出来
         BitmapImage bitmapImage = new BitmapImage();
         bitmapImage.SetSource(StreamInfo.Stream);
    
         _writeBitmap = new WriteableBitmap(bitmapImage);
         PreviewImage.Source = _writeBitmap;         
    
         // 保存示例图片的流,用于接下来添加滤镜
         _imageStreamOrigin = StreamInfo.Stream;
    
     }


    10)添加两个 RadioButton 的 Checked 事件,用来为图片运用不同的滤镜效果:

    // 灰色
     private void Gray_RadioButton_Checked(object sender, RoutedEventArgs e)
     {
         _sketchMode = SketchMode.Gray;
         CreatePreviewImage();
     }
    
     // 彩色
     private void Color_RadioButton_Checked(object sender, RoutedEventArgs e)
     {
         _sketchMode = SketchMode.Color;
         CreatePreviewImage();
     }

    11)最后添加 CreatePreviewImage() 方法,对图片运用滤镜效果:

    public async void CreatePreviewImage()
    {
        if (_imageStreamOrigin == null || _writeBitmap == null)
        {
            return;
        }
        _imageStreamOrigin.Position = 0;
    
        // 运用这个滤镜效果
        var filters = new IFilter[]
        {
            new SketchFilter(_sketchMode)
        };
    
        using (var source = new StreamImageSource(_imageStreamOrigin))
        using (var filterEffect = new FilterEffect(source) { Filters = filters })
        using (var renderer = new WriteableBitmapRenderer(filterEffect, _writeBitmap))
        {
            await renderer.RenderAsync();
            PreviewImage.Source = _writeBitmap;
        }
    } 

    12)当分别点击“草图滤镜”(SketchFilter)的两个 RadioButton 时,运行效果:

    13) 接下来在LomoFilterPage.xaml 页面中,给示例图片添加 LomoFilter:

    和上面一样,首先添加一个 Image 控件,用来显示图片预览;然后添加两个 Silder控件,分别调整滤镜的亮度、

    饱和度;最后添加两组 RadioButton控件,分别用来调整滤镜的“光晕”模式和“颜色风格”,相应的 XAML如下:

    <!--LayoutRoot 是包含所有页面内容的根网格-->
        <Grid x:Name="LayoutRoot" Background="Transparent" Tap="LayoutRoot_Tap">
            <Image x:Name="PreviewImage"/>
    
            <Grid x:Name="gridControls" Visibility="Collapsed" VerticalAlignment="Bottom" Background="#44ffffff" >
                <Grid.Resources>
                    <Style TargetType="TextBlock">
                        <Setter Property="Margin" Value="20,0,0,0"/>
                        <Setter Property="Foreground" Value="#ffffffff"/>
                        <Setter Property="FontWeight" Value="ExtraBold"/>
                    </Style>
                </Grid.Resources>
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto"/>
                    <RowDefinition Height="auto"/>
                    <RowDefinition Height="auto"/>
                    <RowDefinition Height="auto"/>
                    <RowDefinition Height="auto"/>
                    <RowDefinition Height="auto"/>
                    <RowDefinition Height="auto"/>
                    <RowDefinition Height="auto"/>
                </Grid.RowDefinitions>
                <TextBlock Text="亮度:"/>
                <Slider Grid.Row="1" Value="0.5" Minimum="0" Maximum="1" ValueChanged="brightnessSlider_ValueChanged"/>
                <TextBlock Grid.Row="2" Text="饱和度:"/>
                <Slider Grid.Row="3" Value="0.5" Minimum="0" Maximum="1" ValueChanged="saturationSlider_ValueChanged"/>
                <TextBlock Grid.Row="4" Text="光晕:"/>
                <StackPanel Orientation="Horizontal" Grid.Row="5">
                    <RadioButton Content="Low" GroupName="LomoVignetting" Checked="lowRadioButton_Checked"/>
                    <RadioButton Content="Medium" GroupName="LomoVignetting" Checked="medRadioButton_Checked"/>
                    <RadioButton Content="High" GroupName="LomoVignetting" Checked="highRadioButton_Checked"/>
                </StackPanel>
    
                <TextBlock Grid.Row="6" Text="风格:"/>
                <StackPanel Orientation="Horizontal" Grid.Row="7">
                    <RadioButton Content="Red" GroupName="Style" Checked="Red_RadioButton_Checked"/>
                    <RadioButton Content="Green"  GroupName="Style" Checked="Green_RadioButton_Checked"/>
                    <RadioButton Content="Blue"  GroupName="Style" Checked="Blue_RadioButton_Checked"/>
                    <RadioButton Content="Yellow"  GroupName="Style" Checked="Yellow_RadioButton_Checked"/>
                </StackPanel>
            </Grid>
        </Grid>

    14)在相应的 C# 页面,首先声明 6个变量,分别保存原始图片流,和滤镜的设置参数:

      // 使用滤镜
      double _brightness = 0.5;
      double _saturation = 0.5;
      LomoVignetting _lomoVignetting = LomoVignetting.Medium; //光晕
      LomoStyle _lomoStyle = LomoStyle.Neutral;
    
      Stream _imageStreamOrigin;// 保存图片的原始数据
      WriteableBitmap _writeBitmap;// 输出结果


    15)在构造函数中,首先读取示例图片的流,显示未经过滤镜处理的图片:

    public LomoFilterPage()
     {
         InitializeComponent();
    
         // 获取 xap 包中的 图片
         StreamResourceInfo StreamInfo = App.GetResourceStream(new Uri("Sample.jpg", UriKind.Relative));
    
         // 先把未经过滤镜处理的示例图片显示出来
         BitmapImage bitmapImage = new BitmapImage();
         bitmapImage.SetSource(StreamInfo.Stream);
    
         _writeBitmap = new WriteableBitmap(bitmapImage);
         PreviewImage.Source = _writeBitmap;           
    
         // 保存示例图片的流,用于接下来添加滤镜
         _imageStreamOrigin = StreamInfo.Stream;
     }

    16)然后定义一个修改滤镜的方法,每当 Silder 控件或者 RadioButton 控件修改滤镜参数的时候,调用一次这个方法:

    public async void CreatePreviewImage()
     {
         if (_imageStreamOrigin == null || _writeBitmap == null)
         {
             return;
         }
         _imageStreamOrigin.Position = 0;
                     
         // 运用这个滤镜效果
         var filters = new IFilter[]
         {
           new LomoFilter(_brightness, _saturation, _lomoVignetting, _lomoStyle)
         };
    
         using (var source = new StreamImageSource(_imageStreamOrigin))
         using (var filterEffect = new FilterEffect(source) { Filters = filters })
         using (var renderer = new WriteableBitmapRenderer(filterEffect, _writeBitmap))
         {
             await renderer.RenderAsync();
             PreviewImage.Source = _writeBitmap;
         }
     }

    改进上面 CreatePreviewImage() 方法

    因为在给图片运用滤镜效果的时候,比如在拖动 Silder 的过程中,因为上一次方法调用还没有完成,

    也就是当代码执行到 await renderer.RenderAsync(); 时,异步线程的操作还没有执行完,下一次

    代码再次执行,就可能会引发 线程安全 的问题,所以用一个小技巧修改一下上面的代码,使用一个全局

    的 IsBusying 布尔值,控制线程的调用:

            bool IsBusying = false;
            public async void CreatePreviewImage()
            {          
                if (_imageStreamOrigin == null || _writeBitmap == null)
                {
                    return;
                }
    
                if (IsBusying)
                {
                    return; // 如果正在运用一组参数,则返回
                }
                IsBusying = true;
    
                _imageStreamOrigin.Position = 0;
    
                // 运用这个滤镜效果
                var filters = new IFilter[]
                {
                  new LomoFilter(_brightness, _saturation, _lomoVignetting, _lomoStyle)
                };
    
                using (var source = new StreamImageSource(_imageStreamOrigin))
                using (var filterEffect = new FilterEffect(source) { Filters = filters })
                using (var renderer = new WriteableBitmapRenderer(filterEffect, _writeBitmap))
                {
                    await renderer.RenderAsync();           
                    
                    //Windows.Foundation.IAsyncOperation<WriteableBitmap> ia = renderer.RenderAsync();
    
                    //ia.Cancel();
    
                    PreviewImage.Source = _writeBitmap;
                }
    
                IsBusying = false;
            }
    View Code

    当然,在调用复杂的情况时,可以使用 System.Threading.Semaphore 类 来限制访问同一资源的线程数量,

    或者 System.Threading.AutoResetEvent 控制线程的事件执行。

    17)下面添加 SIider 和 RadioButton 控件的事件触发的代码,下面的代码虽然比较多,但很容易理解:

    #region 参数调整
     private void brightnessSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
     {
         _brightness = 1.0 - e.NewValue;
         CreatePreviewImage();
     }
    
     private void saturationSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
     {
         _saturation = e.NewValue;
         CreatePreviewImage();
     }
    
     protected void lowRadioButton_Checked(object sender, System.Windows.RoutedEventArgs e)
     {
         _lomoVignetting = LomoVignetting.Low;
         CreatePreviewImage();
     }
    
     protected void medRadioButton_Checked(object sender, System.Windows.RoutedEventArgs e)
     {
         _lomoVignetting = LomoVignetting.Medium;
         CreatePreviewImage();
     }
    
     protected void highRadioButton_Checked(object sender, System.Windows.RoutedEventArgs e)
     {
         _lomoVignetting = LomoVignetting.High;
         CreatePreviewImage();
     }
    
     private void Red_RadioButton_Checked(object sender, RoutedEventArgs e)
     {
         _lomoStyle = LomoStyle.Red;
         CreatePreviewImage();
     }
    
     private void Green_RadioButton_Checked(object sender, RoutedEventArgs e)
     {
         _lomoStyle = LomoStyle.Green;
         CreatePreviewImage();
     }
    
     private void Blue_RadioButton_Checked(object sender, RoutedEventArgs e)
     {
         _lomoStyle = LomoStyle.Blue;
         CreatePreviewImage();
     }
    
     private void Yellow_RadioButton_Checked(object sender, RoutedEventArgs e)
     {
         _lomoStyle = LomoStyle.Yellow;
         CreatePreviewImage();
     }
     #endregion
    View Code

    18)运行工程:

    19) 总结:本实验代码量比较少,也很容易理解。有关 Nokia Imaging SDK 滤镜使用流程,请参考相关文档

    工程下载链接: http://pan.baidu.com/s/1eXV4q

    在运行源代码时,会出现一个编译错误: 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

  • 相关阅读:
    mysql分表场景分析与简单分表操作
    Linux内嵌汇编
    window 和 linux x64差别
    sourcetree和gitlab配置图解
    QT如何管理组件(解决“要继续此操作,至少需要一个有效且已启用的储存库”问题)
    QT5.x应用在Mac OS X和Windows平台的发布过程
    python中读写二进制文件
    mysql分表的3种方法
    MySQL-C++封装类
    MySQL删除数据库时无响应解决办法
  • 原文地址:https://www.cnblogs.com/hebeiDGL/p/3487177.html
Copyright © 2011-2022 走看看