Capturing Raw Images from the Microsoft Surface  

Friday, January 22 2010

Surface Multi-touch

As I mentioned in a previous post the Microsoft Surface implements multi-touch using infrared computer vision as opposed to a capacitive approach. This is interesting for a couple of reasons. First it allows the Surface to recognize a very large number of touches. Second, it allows ambitious developers to tap directly into this infrared image data to perform more complex operations (like shape recognition). Getting at this information however is not entirely straight forward though. To simply things I created an attached behavior.

Attached Behaviors

Attached behaviors are something that I’ve blogged about before. They are a very convenient way to add user interface behavior to controls without having to implement a proper subclass. This behavior also implements a custom attached event, which allows you to easily handle and process images captured from the Surface.

Using the Behavior

Using the behavior is simple; you just have to include the library in your solution, add the xmlns and set a couple of attached properties and an event handler:


<s:SurfaceWindow
  behaviors:SurfaceWindowRawImageCapture.IsEnabled="True"
  behaviors:SurfaceWindowRawImageCapture.RawImageCaptured="YourEventHandler">
  (...)
</s:SurfaceWindow>

Optional Parameters

This behavior is designed to be flexible. There are several parameters that allow you to take advantage of this flexibility.

UseExplicitCapture=(true | false)

Setting this property to true will disable the attached event from being raised. It is false by default. Use it if you want to capture images programmatically which is explained below.

SaveTo=”C:\path\to\captured\images

Often it may be necessary to save the images that you capture to a specific location. If you set this property all images captured by the behavior will be saved to the specified directory.

Capturing Images Programmatically

The one drawback to the way that the Surface SDK allows developers to capture raw images is that the ContactDown event must be handled on the instance of the SurfaceWindow itself. What that means is that your attached event handler has to also be on the SurfaceWindow itself. The solution to this limitation is to call the behavior programmatically from your own code:


SurfaceWindowRawImageCapture.CaptureRawImageAsync(
    Application.Current.MainWindow as SurfaceWindow,
    new Rect(100, 100, 100, 100),
    result =>
    {
        // Code to execute when the result has been captured
    });

The Rect that is passed to the method defines an area to crop the entire Surface image. This is useful if you are only interested in a small sub-area of the total Surface. The callback that is passed to the method will be executed after the image has been captured.

Let me know if you run into any issues with the behavior by emailing me: charlie [you know] robbins [obviously] gmail [you know] com. As always, all of this code is available under the MIT license on GitHub.


  • Posted by Charlie Robbins

Why would Facebook suggest porn stars as friends?  

Wednesday, January 20 2010

How it happened

It’s actually a very simple story. I’m on Facebook and I see the following image:

WTF-Facebook

Now I start to think to myself, who is this person? A quick Google search reveals very simply that Gianna is a porn star. Gianna is also most likely not her real name (duh!). Now the rest of this discussion has nothing to do with porn (sorry to disappoint), but merely a thought experiment as to how whatever silly algorithm they have running at Facebook could have calculated that this was a relevant suggestion.


Read More...
  • Posted by Charlie Robbins

Fudging the non-client area of Custom Chrome Windows using WPF and Win32  

Friday, January 15 2010

Now that I’m back from staycation I’ve been looking around at some miscellany that needs to be done at the Lab. One of those items used my open-source (MIT ftw)Custom Chrome Window library. In the process of using it I came across a little bug that’s discussed on the WPF Window Chrome site here.

Basically, even though the “Caption bar” (aka “Title bar,” aka “Window bar,” aka “Non-client Window area”) was hidden, the Window.Top and Window.Left calculations take it into account. After a colleague of mine did some serious Google-foo on Win32 we found this solution which has been added to the library on GitHub. The solution is outlined below, starting with including some Win32 API calls:


public static class SafeNativeMethods
{
    [DllImport("user32.dll")]
    public static extern int GetWindowLong(IntPtr hwnd, int index);

    [DllImport("user32.dll")]
    public static extern int SetWindowLong(IntPtr hwnd, int index, int newStyle);

    [DllImport("user32.dll")]
    public static extern bool SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter, int x, int y, int width, int height, uint flags);

    [DllImport("user32.dll")]
    public static extern IntPtr SendMessage(IntPtr hwnd, uint msg, IntPtr wParam, IntPtr lParam);

    internal const int WS_CHILD = 0x40000000;
    internal const int WS_VISIBLE = 0x10000000;
    internal const int LBS_NOTIFY = 0x00000001;
    internal const int HOST_ID = 0x00000002;
    internal const int LISTBOX_ID = 0x00000001;
    internal const int WS_VSCROLL = 0x00200000;
    internal const int WS_BORDER = 0x00800000;


    public const int GWL_EXSTYLE = -20;
    public const int GWL_STYLE = -16;
    public const int WS_EX_DLGMODALFRAME = 0x0001;
    public const int SWP_NOSIZE = 0x0001;
    public const int SWP_NOMOVE = 0x0002;
    public const int SWP_NOZORDER = 0x0004;
    public const int SWP_FRAMECHANGED = 0x0020;
    public const uint WM_SETICON = 0x0080;
    public const int WS_DLGFRAME = 0x00400000;

    public const int WS_SYSMENU = 0x80000;
    public const int WS_MINIMIZEBOX = 0x20000;
    public const int WS_MAXIMIZEBOX = 0x10000;
}

After which we need to call into these methods in the CustomChromeWindow class:


protected override void OnSourceInitialized(EventArgs e)
{
    base.OnSourceInitialized(e);

    // Get this window's handle
    IntPtr hwnd = new WindowInteropHelper(this).Handle;

    // Change the extended window style to not show a window icon
    int extendedStyle = SafeNativeMethods.GetWindowLong(hwnd, SafeNativeMethods.GWL_EXSTYLE);
    int style = SafeNativeMethods.GetWindowLong(hwnd, SafeNativeMethods.GWL_STYLE);

    SafeNativeMethods.SetWindowLong(
        hwnd, 
        SafeNativeMethods.GWL_STYLE,
        style & ~SafeNativeMethods.WS_SYSMENU & ~SafeNativeMethods.WS_MINIMIZEBOX & ~SafeNativeMethods.WS_MAXIMIZEBOX & SafeNativeMethods.WS_DLGFRAME);

    // Update the window's non-client area to reflect the changes
    SafeNativeMethods.SetWindowPos(
        hwnd, 
        IntPtr.Zero, 
        0, 0, 0, 0,
        SafeNativeMethods.SWP_NOMOVE | SafeNativeMethods.SWP_NOSIZE | SafeNativeMethods.SWP_NOZORDER | SafeNativeMethods.SWP_FRAMECHANGED);
}

Hopefully you’ll never have to wallow in the pain of custom window chrome, but if you do take a look at the library on GitHub.


  • Posted by Charlie Robbins

Digital New Years Resolutions  

Sunday, January 03 2010

Top on the list this year was a little “nerd spring cleaning”: getting rid of old electronics and computer parts at the Lower East Side Ecology Center, organizing some files (maybe on DropBox), and finally upgrade from Win7 RC1 to Win7 RTM. Most developers have a lot of software they require to work and I thought that I would share mine for comparison:

Acrobat Reader
Adobe AIR
Adobe CS4
ANTLR
DropBox
F#
Flash 10
Fiddler2
GhostDoc
Git
Google Chrome
Google Talk
Git
IntelliJ
Java (JRE / JDK)
RubyMine
.NET
DirectX
Divx Codec
Blend3
Blend 3 SDK
FxCop
Microsoft Office 2007
Silverlight 3
Silverlight 3 SDK
Silverlight 3 Tools for VS2010
Oslo (aka SQL Modeling)
SQL Studio Express Edition
StyleCop
Microsoft Surface SDK
Visual Studio 2010
XNA 2.0
Firefox
MySQL
Paint.NET
PowerISO
Python 2.6.2
QuickTime
Regionerate
Rooler
Ruby 1.8.7
Skype
Songbird
TortoiseSVN
TweetDeck
VLC
WinMerge
WinRAR
Xvid

If I’m missing anything, let me know!


Read More...
  • Posted by Charlie Robbins