Live camera filters for Windows Phone apps

Live camera filters for Windows Phone apps

Live camera filters for Windows Phone apps

This tutorial demonstrates you how you can create a Windows Phone app that will stream and apply a basic image filter on it.
You can use the filter from this tutorial, or any other basic image filter. The filter that we use here is an invert filter, therefore all colors in the target picture will be inverted.

While the technique to filter images remains unchanged, here for each frame, every pixel will be recalculated. Therefore it is a an intensive process that should be done as efficient as it can be. Especially when you use more than 1 filter, or filters where each pixel is affected by multiple other pixels.

  • In Visual Studio create a new blank Windows Phone App project for Windows Phone 7.1 or 8.
  • Firstly go to MainPage.xaml and set our orientation to landscape by updating the following in our PhoneApplicationPage tag:
    SupportedOrientations="Landscape" Orientation="Landscape"
    
  • Add an Image in which we will stream the filtered content:
    <Image Name="cameraView" Stretch="Fill" />
    
  • Then add a VideoBrush where we can connect the camera to. The original camera stream will be sent to this VideoBrush, so set the Visibilty to Collapsed.
    <Rectangle Visibility="Collapsed">
        <Rectangle.Fill>
            <VideoBrush x:Name="cameraBrush" />
        </Rectangle.Fill>
    </Rectangle>
    
  • Go to MainPage.xaml.cs and add the following usings:
    using System;
    using Microsoft.Devices;
    using System.Windows.Media.Imaging;
    using System.Threading;
    
  • Now add a PhotoCamera, the WriteableBitmap we want to stream to, a thread to handle the frames and a ManualResetEvent that helps us wait for the next frame.
    PhotoCamera cam = new PhotoCamera();
    WriteableBitmap mainImage;
    private Thread videoThread;
    private static ManualResetEvent pauseEvent = new ManualResetEvent(true);
    
  • When we navigate to the page, we directly want the video to start. Therefore add an OnNavigatedTo override to initialize the camera and connect it to our VideoBrush:
    protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
    {
       cam = new Microsoft.Devices.PhotoCamera();
       cam.Initialized += new EventHandler<Microsoft.Devices.CameraOperationCompletedEventArgs>(cam_Initialized);
       cameraBrush.SetSource(cam);
    }
    
  • When the page is closed, the camera will have to be disposed again..
    protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
    {
        if (cam != null)
        {
           cam.Dispose();
           cam.Initialized -= cam_Initialized;
        }
    }
    
  • When the camera has initialized, connect the WriteableBitmap to the Image we want to stream to and start the thread that pumps the frames to the image. We do all this in the UI thread.
    void cam_Initialized(object sender, Microsoft.Devices.CameraOperationCompletedEventArgs e)
    {
        this.Dispatcher.BeginInvoke(delegate()
        {
            mainImage = new WriteableBitmap((int)cam.PreviewResolution.Width, (int)cam.PreviewResolution.Height);
            cameraView.Source = mainImage;
            videoThread = new System.Threading.Thread(PumpFrames);
            videoThread.Start();
        });
    }
    
  • Now add the thread that will do all the work. Create an int array to write our pixels to. This will be done with the camera’s preview resolution, we could take the real picture, but then the camera would need to focus each frame etc. and it will all become really slow.
    With a while true the frames will be pumped as long as the thread runs.
    We make sure the previous frame is ready by using the pause event. We don’t want more than one object accessing our frame at the same time. Then copy the preview buffer to our pixel array and reset the pause event.
    We move to the UI thread again. Here we will apply our filter. Of course you could use any filter here. In this example we’ll invert the camera, which is actually quite nice on a live camera stream :)
    We copy the filtered pixels to our image, and tell with invalidate that it needs to redraw.
    Then we set the pause event and our frame is done.
    void PumpFrames()
    {
       int[] ARGBPx = new int[(int)cam.PreviewResolution.Width * (int)cam.PreviewResolution.Height];
     
       while (true)
       {
          pauseEvent.WaitOne();
          cam.GetPreviewBufferArgb32(ARGBPx);
          pauseEvent.Reset();
     
          this.Dispatcher.BeginInvoke(delegate()
          {
            Invert(ARGBPx);
            ARGBPx.CopyTo(mainImage.Pixels, 0);
            mainImage.Invalidate();
            pauseEvent.Set();
          });
       }
    }
    
  • Now only lasts the filter itself. This time we do our invert filter a little more compact for the rest it’s exactly the same as in the previuos tutorial about image filters for Windows Phone. Just a little more compact and quicker.
    public static void Invert(int[] target)
    {
       for (int i = 0; i < target.Length; i++)
          target[i] = (int)(0x00ffffff - (System.UInt32)target[i]);
    }
    

Download Download the Visual Studio 2012 project

Invert live video stream

Invert live video stream

Leave a Reply

Your email address will not be published. Required fields are marked *