Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Image Manipulation in Multitouch Development

0.00/5 (No votes)
3 Apr 2010 2  
In this article, I will describe Image manipulation in Windows 7 multitouch Environment

Introduction

Windows 7 came up with lots of goodies including better resource management, better performance, jumplist management, multitouch functionality & many more. Here I will discuss about developing a simple multitouch application using .NET 3.5 SP1.

Before doing anything, you have to download the Windows 7 Multitouch API. You can download it from here. Extract the downloaded zip file to your local hard drive. Be sure that you are using Windows 7 and you have a multitouch enabled screen to test it out.

Using ManipulationProcessor

Create a WPF application using Visual Studio 2008. This will automatically add an XAML file named Window1.xaml for you. Now add an image to your solution directory & insert it in the XAML. Now your Window1.xaml will look something like this:

<Grid>
<Image Source="images/Hydrangeas.jpg"/>
</Grid>

Add RenderTransform to the image so that we can scale or rotate the image properly. This will produce XAML similar to this:

<Grid>
<Image Source="images/Hydrangeas.jpg" RenderTransformOrigin="0.5,0.5" Width="400">
<Image.RenderTransform>
<TransformGroup>
<ScaleTransform x:Name="trScale" ScaleX="1" ScaleY="1"/>
<RotateTransform x:Name="trRotate" Angle="0"/>
<TranslateTransform x:Name="trTranslate" X="0" Y="0"/>
<SkewTransform AngleX="0" AngleY="0"/>
</TransformGroup>
</Image.RenderTransform>
</Image>
</Grid>

Use proper names when you are adding different types of transform to the transform group. It will be easier for you to handle it from the code behind file. Run your application. This will open up your Window with an image inside it. If you want to drag or rotate the image, this will not work because we haven’t integrated the functionality yet.

Add two project references, i.e. Windows7.Multitouch & Windows7.Multitouch.WPF from the extracted zip folder to your solution. These are the managed API codes for multitouch application development.

Go to your Window1.xaml.cs and be sure that the following namespaces are already included. You may have to add some of them.

using System;
using System.Windows;
using Windows7.Multitouch;
using Windows7.Multitouch.Manipulation;
using Windows7.Multitouch.WPF;

Create two private members inside your partial class:

// object of a .Net Wrapper class for processing multitouch manipulation
private ManipulationProcessor manipulationProcessor = 
		new ManipulationProcessor(ProcessorManipulations.ALL);

// boolean value to check whether you have a multitouch enabled screen
private static bool IsMultitouchEnabled = 
		TouchHandler.DigitizerCapabilities.IsMultiTouchReady;

Now inside the Window Loaded event, write the following lines of code:

// check to see whether multitouch is enabled
if (IsMultitouchEnabled)
{
     // enables stylus events for processor manipulation
     Factory.EnableStylusEvents(this);

     // add the stylus events
     StylusDown += (s, e) => 
     { 
          manipulationProcessor.ProcessDown
		((uint)e.StylusDevice.Id, e.GetPosition(this).ToDrawingPointF()); 
     };
     StylusUp += (s, e) => 
     { 
          manipulationProcessor.ProcessUp
		((uint)e.StylusDevice.Id, e.GetPosition(this).ToDrawingPointF()); 
     };
     StylusMove += (s, e) => 
     { 
          manipulationProcessor.ProcessMove
		((uint)e.StylusDevice.Id, e.GetPosition(this).ToDrawingPointF()); 
     };

     // register the ManipulationDelta event with the manipulation processor
     manipulationProcessor.ManipulationDelta += ProcessManipulationDelta;

     // set the rotation angle for single finger manipulation
     manipulationProcessor.PivotRadius = 2;
}

Write your logic inside the manipulation event handler implementation block. Here I will do rotation, scaling & positioning of the image. Here is my code:

private void ProcessManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
     trTranslate.X += e.TranslationDelta.Width;
     trTranslate.Y += e.TranslationDelta.Height;

     trRotate.Angle += e.RotationDelta * 180 / Math.PI;

     trScale.ScaleX *= e.ScaleDelta;
     trScale.ScaleY *= e.ScaleDelta;
}

From the ManipulationDeltaEventArgs, you can get various values and depending upon them, you can implement your functionality in this block. TranslateTransform will position the image, RotateTransform will do the rotation and the ScaleTransform will resize the image. Run your project to test your first multitouch application.

Using the Stylus

Here I will show you how to manage multitouch events for all the images separately. See one such image manipulation demo here.

For this, we have to assign a unique touch-id for each finger on the screen. As long as the finger touches the screen, the associated touch-id will remain the same for that particular finger. If the user releases his finger, the system will release the touch-id and that can be again assigned by the system automatically on next touch. So, how can we get the touch-id? You can get it from the StylusEventArgs (i.e., args.StylusDevice.Id). The stylus device will automatically generate this ID for each touch; the only thing is you have to assign it with the respective finger touch.

First of all, we will create a User Control which will consist of a single image and the XAML code for its RenderTransform. This is the same thing we did in the previous post which was inside the Window, but here, it will be inside the User Control (Picture class). Create a DependencyProperty to assign the ImageLocation dynamically.

<UserControl x:Class="Windows7MultitouchDemo.Picture"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Image Source="{Binding Path=ImageLocation}" Stretch="Fill" Width="Auto"
           Height="Auto"  RenderTransformOrigin="0.5, 0.5">
        <Image.RenderTransform>
            <TransformGroup>
                <RotateTransform x:Name="trRotate"/>
                <ScaleTransform x:Name="trScale"/>
                <TranslateTransform x:Name="trTranslate"/>
            </TransformGroup>
        </Image.RenderTransform>
    </Image>
</UserControl>

To track the multi-touch simultaneously for the above “Picture” user control, you can use the PictureTracker class which comes with the Windows 7 Training Kit. You can download it from the Microsoft website. It looks similar to this:

/// <summary>
/// Track a single picture
/// </summary>
public class PictureTracker
{
   private Point _prevLocation;
   public Picture Picture { get; set; }
   public void ProcessDown(Point location)
   {
       _prevLocation = location;
   }
   public void ProcessMove(Point location)
   {
       Picture.X += location.X - _prevLocation.X;
       Picture.Y += location.Y - _prevLocation.Y;
       _prevLocation = location;
   }
   public void ProcessUp(Point location)
   {
       //Do Nothing, We might have another touch-id that is
       //still down
   }
}

Now, we have to store all the active touch-ids associated with the PictureTracker class. So, we will use a Dictionary for that. We will use the same PictureTrackerManager class which again comes with the Windows 7 Training Kit.

private readonly Dictionary<int, PictureTracker> _pictureTrackerMap;

Create an instance of the PictureTrackerManager class inside your Window1.xaml.cs and register the stylus events with the PictureTrackerManager events. So now, whenever a touch occurs on the Picture, the PictureTrackerManager will first find the associated touch-id for the respective instance and raise an event to process the same.

//Register for stylus (touch) events
StylusDown += _pictureTrackerManager.ProcessDown;
StylusUp += _pictureTrackerManager.ProcessUp;
StylusMove += _pictureTrackerManager.ProcessMove;

Reference

History

  • 3rd April, 2010: Initial post

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here