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

Imports Microsoft.Kinect


Class MainWindow
#Region "メンバー変数"
    Private _Kinect As KinectSensor
    Private _ColorImageBitmap As WriteableBitmap
    Private _ColorImageBitmapRect As Int32Rect
    Private _ColorImageStride As Integer
    Private _ColorImagePixelData() As Byte
#End Region

#Region "コンストラクタ"
    Private Sub MainWindow_Loaded(sender As Object,
                                  e As System.Windows.RoutedEventArgs) Handles Me.Loaded
        Call DiscoverKinectSensor()
    End Sub

    Private Sub MainWindow_Unloaded(sender As Object,
                                    e As System.Windows.RoutedEventArgs) Handles Me.Unloaded
        Me.Kinect = Nothing
    End Sub
#End Region

#Region "メソッド"
    Private Sub DiscoverKinectSensor()
        AddHandler KinectSensor.KinectSensors.StatusChanged, AddressOf KinectSensors_StatusChanged
        Me.Kinect = KinectSensor.KinectSensors.FirstOrDefault(Function(x)
                                                                  Return x.Status = KinectStatus.Connected
                                                              End Function)
    End Sub

    Private Sub KinectSensors_StatusChanged(sender As Object, e As StatusChangedEventArgs)
        Select Case e.Status
            Case KinectStatus.Connected
                If Me.Kinect Is Nothing Then
                    Me.Kinect = e.Sensor
                    UpdateDisplayStatus("Sensor connected.")
                End If
            Case KinectStatus.Disconnected
                If Me.Kinect Is Nothing Then
                    Me.Kinect = Nothing
                    Me.Kinect = KinectSensor.KinectSensors.FirstOrDefault(Function(x)
                                                                              Return x.Status = KinectStatus.Connected
                                                                          End Function)
                    If Me.Kinect Is Nothing Then
                        UpdateDisplayStatus("No connected device.")
                    End If
                End If
                'TODO: 必要に応じて、他のすべての状態を処理する
        End Select
        If e.Status = KinectStatus.Connected Then
            Me.Kinect = e.Sensor
        End If
    End Sub

    Private Sub Kinect_ColorFrameReady(sender As Object, e As ColorImageFrameReadyEventArgs)
        Using frame As ColorImageFrame = e.OpenColorImageFrame()
            If frame IsNot Nothing Then
                frame.CopyPixelDataTo(Me._ColorImagePixelData)
                Dim element As FrameworkElement = CType(ImageTreatmentSelector.SelectedItem, FrameworkElement)
                If element IsNot Nothing Then
                    Dim tagValue As String = CType(element.Tag, String)
                    Select Case tagValue
                        Case "1"
                            ColorImageElement.Source = BitmapImage.Create(frame.Width,
                                                                          frame.Height,
                                                                          96,
                                                                          96,
                                                                          PixelFormats.Bgr32,
                                                                          Nothing,
                                                                          Me._ColorImagePixelData,
                                                                          frame.Width * frame.BytesPerPixel)
                        Case "2"
                            Me.ColorImageElement.Source = Me._ColorImageBitmap
                            Me._ColorImageBitmap.WritePixels(Me._ColorImageBitmapRect,
                                                             Me._ColorImagePixelData,
                                                             Me._ColorImageStride,
                                                             0)
                        Case "3"
                            Me.ColorImageElement.Source = Me._ColorImageBitmap
                            ShadePixelDataRed(Me._ColorImagePixelData, frame)
                            Me._ColorImageBitmap.WritePixels(Me._ColorImageBitmapRect,
                                                             Me._ColorImagePixelData,
                                                             Me._ColorImageStride,
                                                             0)
                    End Select
                End If
            End If
        End Using
    End Sub

    '*
    '*Listing 2-4
    '*
    'Private Sub Kinect_ColorFrameReady(sender As Object, e As ColorImageFrameReadyEventArgs)
    '    Using frame As ColorImageFrame = e.OpenColorImageFrame()
    '        If frame IsNot Nothing Then
    '            Dim pixelData(frame.PixelDataLength - 1) As Byte
    '            frame.CopyPixelDataTo(pixelData)
    '            ColorImageElement.Source = BitmapImage.Create(frame.Width,
    '                                                          frame.Height,
    '                                                          96,
    '                                                          96,
    '                                                          PixelFormats.Bgr32,
    '                                                          Nothing,
    '                                                          pixelData,
    '                                                          frame.Width * frame.BytesPerPixel)
    '        End If
    '    End Using
    'End Sub
    '*
    '*

    '*
    '*Listing 2-7
    '*
    'Private Sub Kinect_ColorFrameReady(sender As Object, e As ColorImageFrameReadyEventArgs)
    '    Using frame As ColorImageFrame = e.OpenColorImageFrame()
    '        If frame IsNot Nothing Then
    '            Dim pixelData(frame.PixelDataLength - 1) As Byte
    '            frame.CopyPixelDataTo(pixelData)
    '            For i As Integer = 0 To pixelData.Length - 1 Step frame.BytesPerPixel
    '                pixelData(i + 0) = &H0      'Blue 
    '                pixelData(i + 1) = &H0      'Green
    '            Next
    '            Me._ColorImageBitmap.WritePixels(Me._ColorImageBitmapRect,
    '                                             pixelData,
    '                                             Me._ColorImageStride,
    '                                             0)
    '        End If
    '    End Using
    'End Sub
    '*
    '*

    Private Sub ShadePixelDataRed(pixelData As Byte(), frame As ColorImageFrame)
        For i As Integer = 0 To pixelData.Length - 1 Step frame.BytesPerPixel
            pixelData(i + 0) = &H0      'Blue 
            pixelData(i + 1) = &H0      'Green
        Next
    End Sub

    Private Sub StartButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
        Call DiscoverKinectSensor()
    End Sub

    Private Sub StopButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
        If Me.Kinect IsNot Nothing Then
            Me.Kinect = Nothing
        End If
    End Sub

    Private Sub InitializeKinectSensor(sensor As KinectSensor)
        If sensor IsNot Nothing Then
            Dim colorStream As ColorImageStream = sensor.ColorStream

            colorStream.Enable()

            '/* Added in Listing 2-5 */
            Me._ColorImageBitmap = New WriteableBitmap(colorStream.FrameWidth,
                                                       colorStream.FrameHeight,
                                                       96,
                                                       96,
                                                       PixelFormats.Bgr32,
                                                       Nothing)
            Me._ColorImageBitmapRect = New Int32Rect(0,
                                                     0,
                                                     colorStream.FrameWidth,
                                                     colorStream.FrameHeight)
            Me._ColorImageStride = colorStream.FrameWidth * colorStream.FrameBytesPerPixel
            Me.ColorImageElement.Source = Me._ColorImageBitmap
            ReDim Me._ColorImagePixelData(colorStream.FramePixelDataLength - 1)
            '/* Added in Listing 2-5 */

            AddHandler sensor.ColorFrameReady, AddressOf Kinect_ColorFrameReady
            sensor.Start()
        End If
    End Sub

    Private Sub UninitializeKinectSensor(sensor As KinectSensor)
        If sensor IsNot Nothing Then
            sensor.Stop()
            RemoveHandler sensor.ColorFrameReady, AddressOf Kinect_ColorFrameReady
        End If
    End Sub

    'Listing 2-9
    Private Sub TakePictureButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs)
        Dim fileName As String = "snapshot.jpg"
        If File.Exists(fileName) Then
            File.Delete(fileName)
        End If

        Using savedSnapshot As FileStream = New FileStream(fileName, FileMode.CreateNew)
            Dim image As BitmapSource = CType(ColorImageElement.Source, BitmapSource)
            Dim jpgEncoder As JpegBitmapEncoder = New JpegBitmapEncoder
            jpgEncoder.QualityLevel = 70
            jpgEncoder.Frames.Add(BitmapFrame.Create(image))
            jpgEncoder.Save(savedSnapshot)

            savedSnapshot.Flush()
            savedSnapshot.Close()
            savedSnapshot.Dispose()
        End Using
    End Sub

    Private Sub UpdateDisplayStatus(message As String)
        StatusElement.Text = message
    End Sub

#End Region

#Region "プロパティ"
    Public Property Kinect As KinectSensor
        Get
            Return Me._Kinect
        End Get
        Set(value As KinectSensor)
            If Me._Kinect IsNot Nothing Then
                UpdateDisplayStatus("No connected device.")
                UninitializeKinectSensor(Me._Kinect)
                Me._Kinect = Nothing
            End If
            If value IsNot Nothing AndAlso value.Status = KinectStatus.Connected Then
                Me._Kinect = value
                InitializeKinectSensor(Me._Kinect)
                StatusElement.Text = String.Format("{0} - {1}",
                                                   Me._Kinect.UniqueKinectId,
                                                   Me._Kinect.Status)
            Else
                UpdateDisplayStatus("No connected device.")
            End If
        End Set
    End Property
#End Region

End Class
