Applying a filter to a picture on Windows Phone

Applying a filter to a picture on Windows Phone

I’ve been looking for a good image library for Windows Phone (Silverlight) that had an appropriate license for using it inside a project for Marketplace. EmguCV library cannot be used with Windows Phone. Aforge.NET image library cannot be used either, because it depends heavily on System.Drawing. But, Codeplex is again full of cool solutions. One of those is ImageTools for Silverlight which provides additional functionality for loading, saving and manipulation images from different sources and with different formats. It also provides a few common filters that you can apply to images. I’ll show you how!

Downloading the library

Go to http://imagetools.codeplex.com/releases/view/53740 and download the binary + documentation, remembering where you downloaded it, of course. Then go and extract the .rar file you’ve just downloaded. If you don’t know what to use for extracting, try 7-zip. You get both the documentation and the binaries. You’ll need the binaries for the Phone:

ImageTools.dll  
ImageTools.Filtering.dll  
ImageTools.Utils.dll  

Using the filter in a Windows Phone project

Create a new Windows Phone project. Add the dll files I mentioned above to the project references. Other than that, you’ll need the WriteableBitmap extensions, which you install through Package Manager Console.

Install-Package WriteableBitmapEx  

Add the following usings to the MainPage.xaml.cs

using Microsoft.Phone.Tasks;  
using System.Windows.Media.Imaging;  
using ImageTools;  
using ImageTools.Filtering;  

Change the Application and Page title to something that makes sense in MainPage.xaml

<StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">  
      <TextBlock x:Name="ApplicationTitle"
                 Text=".NET IMAGE TOOLS SAMPLE"
                 Style="{StaticResource PhoneTextNormalStyle}"/>
      <TextBlock x:Name="PageTitle"
                 Text="inverter" Margin="9,-7,0,0"
                 Style="{StaticResource PhoneTextTitle1Style}"/>
</StackPanel>  

I named the page Inverter because I use the Inverter filter.

Now, define the UI of the demo application:

<ScrollViewer Grid.Row="1" Margin="12,0,12,0">  
  <Grid x:Name="ContentPanel">
      <StackPanel Name="firstSelection" Visibility="Visible">
          <Button Content="Choose a photo" Padding="16" Click="Button_Click" />
      </StackPanel>
      <StackPanel Name="imageSelectedPanel" Visibility="Collapsed">
          <Image Name="img" Width="400" />
          <Button Content="Invert" Name="btnInvert" Click="btnInvert_Click"/>
          <Button Content="Choose another photo" Click="Button_Click" />
      </StackPanel>
  </Grid>
</ScrollViewer>  

I put the ContentPanel inside the ScrollViewer  because when you load the image it usually takes some space away from the buttons at the bottom. Now, in the MainPage.xaml.cs add:

PhotoChooserTask photoChooser;  
ExtendedImage loadedImage;  
ExtendedImage filteredImage;  
Inverter filter;  
BitmapImage image;  

Since I'll be taking the image from the Windows Phone pictures library, I need the PhotoChooserTask which will return me the picture I select:

photoChooser = new PhotoChooserTask();  
photoChooser.Completed += new EventHandler<PhotoResult>(photoChooser_Completed);  

When the user selects the image from the library, make it the Source of the image you defined in XAML, and create the ExtendedImage object from the ImageTools library:

void photoChooser_Completed(object sender, PhotoResult e)  
  {
      if (e.TaskResult == TaskResult.OK)
      {
          image = new BitmapImage();
          image.SetSource(e.ChosenPhoto);
          img.Source = image;

          WriteableBitmap wb = new WriteableBitmap(image);
          loadedImage = new ExtendedImage();

          loadedImage.SetPixels(image.PixelWidth, image.PixelHeight, wb.ToByteArray());

          firstSelection.Visibility = System.Windows.Visibility.Collapsed;
          imageSelectedPanel.Visibility = System.Windows.Visibility.Visible;
      }
  }

The chooser gets launched when the user selects Choose a photo button:

private void Button_Click(object sender, RoutedEventArgs e)  
  {
      try
      {
          photoChooser.Show();
      }
      catch
      {
          MessageBox.Show("An error occurred");
      }
  }

The picture gets loaded. When the picture gets loaded, you get the button that inverts the picture. Let’s look at the click event handler for that button, where the inverter filter does the job:

          private void btnInvert_Click(object sender, RoutedEventArgs e)
          {
              filter = new Inverter();
              filteredImage = new ExtendedImage(loadedImage);
              filter.Apply(filteredImage, loadedImage, new ImageTools.Rectangle(0,0,loadedImage.PixelWidth, loadedImage.PixelHeight));

              var bitmap = filteredImage.ToBitmap();
              img.Source = bitmap;
          }

The filter object gets created. The filteredImage gets created from the loaded image ExtendedImage. Then the filter gets applied and the filtered image becomes the source for the img defined in XAML.

Here’s what it looks like in the emulator:

imageInvert

Using the PhotoChooserTask while debugging

Now, you will encounter a problem when you try to use the PhotoChooserTask while debugging and Zune running. In order to solve this problem, you need to use the WPConnect tool. Find more details here: http://msdn.microsoft.com/en-us/library/gg180729(v=vs.92).aspx

Shortly, you need to get your device recognized with Zune. After that, close it and open cmd. Navigate to

Program FilesMicrosoft SDKsWindows Phonev7.1ToolsWPConnect

or

Program Files (x86)Microsoft SDKsWindows Phonev7.1ToolsWPConnect

Choose either the x86 or x64, and rune WPConnect.exe tool. That way you’ll be able to debug the project without Zune and therefore use the photo library on your phone! :)

I hope you’ll find the article useful. If you do, leave a comment and help spread the news about the article! :)

Igor Ralic

igor ralic

View Comments
Microsoft Certified Solutions Developer: Windows Store Apps in C#