Imports System
Imports System.Linq
Imports System.Windows
Imports System.Windows.Media
Imports System.Windows.Media.Imaging


Imports Microsoft.Kinect

''' <summary>
''' Interaction logic for MainWindow.xaml
''' </summary>
''' <remarks></remarks>
Class MainWindow
#Region "メンバー変数"
    Private _KinectDevice As KinectSensor
    Private _RawDepthImage As WriteableBitmap
    Private _RawDepthImageRect As Int32Rect
    Private _RawDepthPixelData() As Short
    Private _RawDepthImageStride As Integer
    Private _EnhDepthImage As WriteableBitmap
    Private _EnhDepthImageRect As Int32Rect
    Private _EnhDepthPixelData() As Short
    Private _EnhDepthImageStride As Integer
    Private _TotalFrames As Integer
    Private _StartFrameTime As DateTime
#End Region


#Region "コンストラクタ"
    Sub New()

        ' この呼び出しはデザイナーで必要です。
        InitializeComponent()

        ' InitializeComponent() 呼び出しの後で初期化を追加します。
        AddHandler KinectSensor.KinectSensors.StatusChanged, AddressOf KinectSensors_StatusChanged
        Me.KinectDevice = KinectSensor.KinectSensors.FirstOrDefault(Function(x)
                                                                        Return x.Status = KinectStatus.Connected
                                                                    End Function)
    End Sub
#End Region


#Region "メソッド"
    Private Sub KinectSensors_StatusChanged(sender As Object, e As StatusChangedEventArgs)
        Select Case e.Status
            Case KinectStatus.Initializing,
                KinectStatus.Connected,
                KinectStatus.NotPowered,
                KinectStatus.NotReady,
                KinectStatus.DeviceNotGenuine
                Me.KinectDevice = e.Sensor
            Case KinectStatus.Disconnected
                'TODO: Give the user feedback to plug-in a Kinect device.                    
                Me.KinectDevice = Nothing
            Case Else
                'TODO: Show an error state
        End Select
    End Sub

    Private Sub KinectDevice_DepthFrameReady(sender As Object, e As DepthImageFrameReadyEventArgs)
        Using frame As DepthImageFrame = e.OpenDepthImageFrame()
            If frame IsNot Nothing Then
                frame.CopyPixelDataTo(Me._RawDepthPixelData)
                Me._RawDepthImage.WritePixels(Me._RawDepthImageRect, Me._RawDepthPixelData, Me._RawDepthImageStride, 0)
                CreatePlayerDepthImage(frame, Me._RawDepthPixelData)
            End If
        End Using
        Me._TotalFrames += 1
        FramesPerSecondElement.Text = String.Format("{0:0} fps",
                                                    (Me._TotalFrames / DateTime.Now.Subtract(Me._StartFrameTime).TotalSeconds))
    End Sub

    Private Sub CreatePlayerDepthImage(depthFrame As DepthImageFrame, pixelData() As Short)
        Dim playerIndex As Integer
        Const depthBytePerPixel As Integer = 4
        Dim enhPixelData(depthFrame.Width * depthFrame.Height * depthBytePerPixel - 1) As Byte

        For i As Integer = 0 To pixelData.Length - 1
            Dim j As Integer = i * depthBytePerPixel

            playerIndex = pixelData(i) And DepthImageFrame.PlayerIndexBitmask

            If playerIndex = 0 Then
                enhPixelData(j + 0) = &HFF
                enhPixelData(j + 1) = &HFF
                enhPixelData(j + 2) = &HFF
            Else
                enhPixelData(j + 0) = &H0
                enhPixelData(j + 1) = &H0
                enhPixelData(j + 2) = &H0
            End If
        Next

        Me._EnhDepthImage.WritePixels(Me._EnhDepthImageRect, enhPixelData, Me._EnhDepthImageStride, 0)
    End Sub
#End Region


#Region "プロパティ"
    Public Property KinectDevice As KinectSensor
        Get
            Return Me._KinectDevice
        End Get
        Set(value As KinectSensor)
            If Me._KinectDevice IsNot value Then
                'Uninitialize
                If Me._KinectDevice IsNot Nothing Then
                    Me._KinectDevice.Stop()
                    RemoveHandler Me._KinectDevice.DepthFrameReady, AddressOf KinectDevice_DepthFrameReady
                    Me._KinectDevice.DepthStream.Disable()
                    Me._KinectDevice.SkeletonStream.Disable()

                    Me.RawDepth_Image.Source = Nothing
                    Me.EnhDepth_Image.Source = Nothing
                End If

                Me._KinectDevice = value

                'Initialize
                If Me._KinectDevice IsNot Nothing Then
                    If Me._KinectDevice.Status = KinectStatus.Connected Then
                        Me._KinectDevice.SkeletonStream.Enable()
                        Me._KinectDevice.DepthStream.Enable()

                        Dim depthStream As DepthImageStream = Me._KinectDevice.DepthStream
                        Me._RawDepthImage = New WriteableBitmap(depthStream.FrameWidth,
                                                                depthStream.FrameHeight,
                                                                96,
                                                                96,
                                                                PixelFormats.Gray16, Nothing)
                        Me._RawDepthImageRect = New Int32Rect(0,
                                                            0,
                                                            Math.Ceiling(Me._RawDepthImage.Width),
                                                            Math.Ceiling(Me._RawDepthImage.Height))
                        Me._RawDepthImageStride = depthStream.FrameWidth * depthStream.FrameBytesPerPixel
                        ReDim Me._RawDepthPixelData(depthStream.FramePixelDataLength - 1)
                        Me.RawDepth_Image.Source = Me._RawDepthImage

                        Me._EnhDepthImage = New WriteableBitmap(depthStream.FrameWidth,
                                                                depthStream.FrameHeight,
                                                                96,
                                                                96,
                                                                PixelFormats.Bgr32,
                                                                Nothing)
                        Me._EnhDepthImageRect = New Int32Rect(0,
                                                              0,
                                                              Math.Ceiling(Me._EnhDepthImage.Width),
                                                              Math.Ceiling(Me._EnhDepthImage.Height))
                        Me._EnhDepthImageStride = depthStream.FrameWidth * 4
                        ReDim Me._EnhDepthPixelData(depthStream.FramePixelDataLength - 1)
                        Me.EnhDepth_Image.Source = Me._EnhDepthImage

                        AddHandler Me._KinectDevice.DepthFrameReady, AddressOf KinectDevice_DepthFrameReady
                        Me._KinectDevice.Start()

                        Me._StartFrameTime = DateTime.Now
                    End If
                End If
            End If
        End Set
    End Property
#End Region

End Class
