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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM