Nokia Imaging SDK濾鏡使用入門

 

簡要說明html

經過對示例圖片分別運用 LomoFilterSketchFilter兩個濾鏡(Nokia Imaging SDK 內置),安全

來學習濾鏡的基本使用和參數的設置。本工程的代碼量比較少,也很容易理解。異步

版本 NokiaImagingSDK  1.0.272.0async

 

下面是這個 demo 的完成步驟:ide

1)經過 Visual Studio 2012 新建一個Windows Phone 8 的工程,命名爲「FilterParametersSample」:函數

 

2) 右鍵單擊工程的「引用」,選擇「管理 NuGet程序包」:學習

在右上角搜索框輸入「Nokia Imaging SDK」,並安裝該 SDK:spa

 

3)由於本次實驗使用模擬器調試,因此須要在「配置管理器」選擇「x86」(Visual Studio菜單 -> 生成 -> 配置管理器):線程

注:關於添加 Nokia Imaging SDK後 VS 的設置請參考:Download and add the libraries to the project3d

 

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

相關文章
相關標籤/搜索