//------------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
//------------------------------------------------------------------------------
namespace Microsoft.Samples.Kinect.DepthBasics
{
using System;
using System.Globalization;
using System.IO;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Microsoft.Kinect;
///
/// Interaction logic for MainWindow.xaml
///
public partial class MainWindow : Window
{
///
/// Active Kinect sensor
///
private KinectSensor sensor;
///
/// Bitmap that will hold color information
///
private WriteableBitmap colorBitmap;
///
/// Intermediate storage for the depth data received from the camera
///
private DepthImagePixel[] depthPixels;
///
/// Intermediate storage for the depth data converted to color
///
private byte[] colorPixels;
///
/// Initializes a new instance of the MainWindow class.
///
public MainWindow()
{
InitializeComponent();
}
///
/// Execute startup tasks
///
/// object sending the event
/// event arguments
private void WindowLoaded(object sender, RoutedEventArgs e)
{
// Look through all sensors and start the first connected one.
// This requires that a Kinect is connected at the time of app startup.
// To make your app robust against plug/unplug,
// it is recommended to use KinectSensorChooser provided in Microsoft.Kinect.Toolkit (See components in Toolkit Browser).
foreach (var potentialSensor in KinectSensor.KinectSensors)
{
if (potentialSensor.Status == KinectStatus.Connected)
{
this.sensor = potentialSensor;
break;
}
}
if (null != this.sensor)
{
// Turn on the depth stream to receive depth frames
this.sensor.DepthStream.Enable(DepthImageFormat.Resolution640x480Fps30);
// Allocate space to put the depth pixels we'll receive
this.depthPixels = new DepthImagePixel[this.sensor.DepthStream.FramePixelDataLength];
// Allocate space to put the color pixels we'll create
this.colorPixels = new byte[this.sensor.DepthStream.FramePixelDataLength * sizeof(int)];
// This is the bitmap we'll display on-screen
this.colorBitmap = new WriteableBitmap(this.sensor.DepthStream.FrameWidth, this.sensor.DepthStream.FrameHeight, 96.0, 96.0, PixelFormats.Bgr32, null);
// Set the image we display to point to the bitmap where we'll put the image data
this.Image.Source = this.colorBitmap;
// Add an event handler to be called whenever there is new depth frame data
this.sensor.DepthFrameReady += this.SensorDepthFrameReady;
// Start the sensor!
try
{
this.sensor.Start();
}
catch (IOException)
{
this.sensor = null;
}
}
if (null == this.sensor)
{
this.statusBarText.Text = Properties.Resources.NoKinectReady;
}
}
///
/// Execute shutdown tasks
///
/// object sending the event
/// event arguments
private void WindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
{
if (null != this.sensor)
{
this.sensor.Stop();
}
}
///
/// Event handler for Kinect sensor's DepthFrameReady event
///
/// object sending the event
/// event arguments
private void SensorDepthFrameReady(object sender, DepthImageFrameReadyEventArgs e)
{
using (DepthImageFrame depthFrame = e.OpenDepthImageFrame())
{
if (depthFrame != null)
{
// Copy the pixel data from the image to a temporary array
depthFrame.CopyDepthImagePixelDataTo(this.depthPixels);
// Get the min and max reliable depth for the current frame
int minDepth = depthFrame.MinDepth;
int maxDepth = depthFrame.MaxDepth;
// Convert the depth to RGB
int colorPixelIndex = 0;
for (int i = 0; i < this.depthPixels.Length; ++i)
{
// Get the depth for this pixel
short depth = depthPixels[i].Depth;
// To convert to a byte, we're discarding the most-significant
// rather than least-significant bits.
// We're preserving detail, although the intensity will "wrap."
// Values outside the reliable depth range are mapped to 0 (black).
// Note: Using conditionals in this loop could degrade performance.
// Consider using a lookup table instead when writing production code.
// See the KinectDepthViewer class used by the KinectExplorer sample
// for a lookup table example.
byte intensity = (byte)(depth >= minDepth && depth <= maxDepth ? depth : 0);
// Write out blue byte
this.colorPixels[colorPixelIndex++] = intensity;
// Write out green byte
this.colorPixels[colorPixelIndex++] = intensity;
// Write out red byte
this.colorPixels[colorPixelIndex++] = intensity;
// We're outputting BGR, the last byte in the 32 bits is unused so skip it
// If we were outputting BGRA, we would write alpha here.
++colorPixelIndex;
}
// Write the pixel data into our bitmap
this.colorBitmap.WritePixels(
new Int32Rect(0, 0, this.colorBitmap.PixelWidth, this.colorBitmap.PixelHeight),
this.colorPixels,
this.colorBitmap.PixelWidth * sizeof(int),
0);
}
}
}
///
/// Handles the user clicking on the screenshot button
///
/// object sending the event
/// event arguments
private void ButtonScreenshotClick(object sender, RoutedEventArgs e)
{
if (null == this.sensor)
{
this.statusBarText.Text = Properties.Resources.ConnectDeviceFirst;
return;
}
// create a png bitmap encoder which knows how to save a .png file
BitmapEncoder encoder = new PngBitmapEncoder();
// create frame from the writable bitmap and add to encoder
encoder.Frames.Add(BitmapFrame.Create(this.colorBitmap));
string time = System.DateTime.Now.ToString("hh'-'mm'-'ss", CultureInfo.CurrentUICulture.DateTimeFormat);
string myPhotos = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
string path = Path.Combine(myPhotos, "KinectSnapshot-" + time + ".png");
// write the new file to disk
try
{
using (FileStream fs = new FileStream(path, FileMode.Create))
{
encoder.Save(fs);
}
this.statusBarText.Text = string.Format("{0} {1}", Properties.Resources.ScreenshotWriteSuccess, path);
}
catch (IOException)
{
this.statusBarText.Text = string.Format("{0} {1}", Properties.Resources.ScreenshotWriteFailed, path);
}
}
///
/// Handles the checking or unchecking of the near mode combo box
///
/// object sending the event
/// event arguments
private void CheckBoxNearModeChanged(object sender, RoutedEventArgs e)
{
if (this.sensor != null)
{
// will not function on non-Kinect for Windows devices
try
{
if (this.checkBoxNearMode.IsChecked.GetValueOrDefault())
{
this.sensor.DepthStream.Range = DepthRange.Near;
}
else
{
this.sensor.DepthStream.Range = DepthRange.Default;
}
}
catch (InvalidOperationException)
{
}
}
}
}
}