NUI/Microsoft PixelSense(Old Surface)

서피스2 :: 픽셀센스™에 의한 적외선 이미지 스캔하는 클래스(WPF)

길버트리 2011. 9. 27. 19:59
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Interop;
using System.Diagnostics;
using Microsoft.Surface.Core;
using System.Windows.Media;

namespace HugeFlow.Surface
{
    /// 
    /// 화면을 적외선 스캔하는 클래스
    /// 
    public class Scanner
    {
        #region 프로퍼티

        /// 
        /// 스캔 중인지 여부
        /// 
        public bool IsScanning { get; private set; }

        /// 
        /// 스캔 어플리케이션 윈도우
        /// 
        public Window ApplicationWindow { get; private set; }

        #endregion 프로퍼티

        #region 멤버

        private IntPtr _windowHandle;
        private TouchTarget _touchTarget;
        private Rect _scanArea;

        #endregion 멤버

        /// 
        /// Application Window를 인자로 소비하는 생성자
        /// 
        /// 
        public Scanner(Window window)
        {
            Debug.Assert(window != null);

            ApplicationWindow = window;

            WindowInteropHelper wih = new WindowInteropHelper(window);
            _windowHandle = wih.Handle;
        }

        /// 
        /// 스캔 비동기 호출
        /// 
        /// 
        public void ScanAsync(Rect scanArea)
        {
            if (IsScanning == true)
                throw new InvalidOperationException("Is scanning...");

            _scanArea = scanArea;

            IsScanning = true;

            // Create a target for surface input.
            _touchTarget = new TouchTarget(_windowHandle, EventThreadChoice.OnBackgroundThread);
            _touchTarget.EnableInput();

            // Enable the normalized raw-image.
            _touchTarget.EnableImage(ImageType.Normalized);

            // Hook up a callback to get notified when there is a new frame available
            _touchTarget.FrameReceived += new EventHandler(_touchTarget_FrameReceived);
        }

        /// 
        /// 스캔 비동기 호출
        /// 
        /// 
        public void ScanAsync(FrameworkElement fe)
        {
            Rect boundInHostCoordinates = (fe.TransformToVisual(ApplicationWindow).TransformBounds(new Rect()
            {
                X = 0,
                Y = 0,
                Width = fe.ActualWidth,
                Height = fe.ActualHeight
            }));
            ScanAsync(boundInHostCoordinates);
        }

        void _touchTarget_FrameReceived(object sender, FrameReceivedEventArgs e)
        {
            _touchTarget.FrameReceived -= _touchTarget_FrameReceived;

            byte[] normalizedImage = null;
            e.UpdateRawImage(
                ImageType.Normalized,
                normalizedImage,
                (int)_scanArea.Left, 
                (int)_scanArea.Top,
                (int)_scanArea.Width,
                (int)_scanArea.Height);

            OnScanCompleted(normalizedImage);

            IsScanning = false;
        }


        #region 이벤트들

        #region ScanCompleted

        public event RoutedPropertyChangedEventHandler ScanCompleted;

        private void OnScanCompleted(byte[] imageData)
        {
            if (ScanCompleted == null)
                return;

            ScanCompleted(this, new RoutedPropertyChangedEventArgs(null, imageData));
        }

        #endregion ScanCompleted
        #endregion 이벤트들
    }
}




서피스2 SDK의 샘플 중 XNA로 되어 있는 RawImageVisualizer 소스를 참고해서 WPF용으로 만들어 봤습니다.
잘못된 부분, 보완할 부분 발견하시면 지적을 부탁드립니다.